home *** CD-ROM | disk | FTP | other *** search
/ Shareware Grab Bag / Shareware Grab Bag.iso / 007 / vtkerma2.arc / MSYIBM.ASM < prev   
Encoding:
Assembly Source File  |  1986-02-13  |  98.3 KB  |  3,867 lines

  1.     PAGE 59, 132
  2.  
  3.     TITLE MSYIBM -- Module to perform VT100 emulation on IBM PC
  4.  
  5. ; Update 7 Jan 86
  6.  
  7. IF1
  8.  %OUT >> Starting pass 1
  9. ELSE
  10.  %OUT >> Starting pass 2
  11. ENDIF
  12.  
  13.     PUBLIC Term_PC, Gss, Close_Screen_PC, Get_Screen_Segment, Check_Table
  14.     PUBLIC Set_up_script_processor_PC, Screen_Image_ptr, Mode_Line_ptr
  15.     PUBLIC Old_Image, Set_up_dynamic_memory
  16.     PUBLIC Save_command_mode_screen, Restore_command_mode_screen
  17.  
  18.     .SALL
  19.  
  20. ;***************************************************************************
  21.  
  22. ; *Definitions* ...
  23.  
  24. ; Global defs
  25.  
  26.     INCLUDE MsDefs.H
  27.  
  28. ; Local defs
  29.  
  30. Screen    EQU 10h            ; BIOS screen call
  31. Kb    EQU 16h            ; BIOS keyboard call
  32.  
  33. PrScan    EQU 72h            ; print-screen scan code...
  34.  
  35. Caps_State EQU 40h        ; CAPS LOCK on
  36. Num_State EQU 20h        ; NUM LOCK on
  37.  
  38. alt_shift EQU 8H        ; alt shift key down
  39. ctl_shift EQU 4H        ; ctl key down
  40. left_shift EQU 2H        ; left shift key down
  41. right_shift EQU 1H        ; right shift key down
  42.  
  43. timer    EQU 40h            ; timer port
  44. bel_prt    EQU 61h            ; speaker control
  45.  
  46. CRT_status_port EQU 3DAh    ; Crt status port
  47. Vertical_retrace EQU 8        ; Vertical retrace in progress
  48.  
  49. ;***************************************************************************
  50.  
  51. ; *Data* ...
  52.  
  53. DataS    SEGMENT public 'datas'
  54.  
  55.     EXTRN PC_Subtype:BYTE, Force_mono:BYTE, m7171:BYTE, AutoWrap:BYTE
  56.     EXTRN Preload_flag:BYTE, Preload_buffer:BYTE, PC_Type:BYTE
  57.     EXTRN Video_page_addresses:WORD, Which_page:BYTE, CRT_Mode:BYTE
  58.     EXTRN Count:WORD, Allow_blast:BYTE
  59.  
  60. ; Fixed data, unchanging ...
  61.  
  62. ; Character decoding dispatch tables ...
  63.  
  64. ; Dispatch for single characters ...
  65.  
  66. ChrTb1    DB     Bell,     Bs,      Tab
  67.     DB    Lf,     Ff,      Cr
  68.     DB    Vt,     ShO,      ShI
  69. NChrTb1    EQU $-ChrTb1
  70. ActTb1    DW     Do_Bell, Do_Bs,   Do_Tab
  71.     DW    IND,     IND,      Do_Cr
  72.     DW    IND,     Do_SO,   Do_SI
  73.     DW    Done_with_char
  74.  
  75. ; Dispatch for things following an escape ...
  76.  
  77. ChrTb2    DB    '[',         '(',         ')'
  78.     DB    '#',         'D',         'E'
  79.     DB    'M',         'Z',         '7'
  80.     DB    '8',         '=',         '>'
  81.     DB    Esc
  82. NChrTb2    EQU $-ChrTb2
  83. ActTb2    DW    Do_left_square,  Do_left_paren,  Do_right_paren
  84.     DW    Do_pound_sign,     IND,         NEL
  85.     DW    RI,         DECID,         DECSC
  86.     DW    DECRC,         DECKPAM,     DECKPNM
  87.     DW    Restart_esc_seq_processing
  88.     DW    Done_with_char
  89.  
  90. ; Dispatch for things following escape [ ...
  91.  
  92. ChrTb3    DB    'A',        'B',    'C'
  93.     DB    'D',        'H',    'J'
  94.     DB    'K',        'c',    'f'
  95.     DB    'h',        'i',    'l'
  96.     DB    'm',        'n',    'q'
  97.     DB    'r',        Esc
  98. NChrTb3    EQU $-ChrTb3
  99. ActTb3    DW     CUU,        CUD,    CUF
  100.     DW    CUB,        CUP,    ED
  101.     DW    EL,        DA,        HVP
  102.     DW    SM,        MC,        RM
  103.     DW    SGR,        DSR,    DECLL
  104.     DW    DECSTBM,    Restart_esc_seq_processing
  105.     DW     Done_with_char
  106.  
  107. ; Dispatch for things following escape ( ...
  108.  
  109. ChrTb4    DB    'B',     '0',      Esc
  110. NChrTb4    EQU $-ChrTb4
  111. ActTb4    DW    Lfp_B,     Lfp_0,   Restart_esc_seq_processing
  112.     DW     Done_with_char
  113.  
  114. ; Dispatch for things following escape ) ...
  115.  
  116. ChrTb5    DB    'B',     '0',      Esc
  117. NChrTb5    EQU $-ChrTb5
  118. ActTb5    DW    Rtp_B,     Rtp_0,   Restart_esc_seq_processing
  119.     DW     Done_with_char
  120.  
  121.  
  122.     EVEN            ; Try for word boundary
  123.  
  124. ; Lookup tables to convert renditions into attribute bytes
  125.  
  126. Color_attributes LABEL BYTE
  127.     DB 007h            ;        * Normal *
  128.     DB 00Fh            ; Bold
  129.     DB 001h            ;     Underscored
  130.     DB 009h            ; Bold     Underscored
  131.     DB 087h            ;               Blinking
  132.     DB 08Fh            ; Bold               Blinking
  133.     DB 081h            ;     Underscored   Blinking
  134.     DB 089h            ; Bold     Underscored   Blinking
  135.     DB 070h            ;                  Inverted
  136.     DB 078h            ; Bold                  Inverted
  137.     DB 071h            ;     Underscored          Inverted
  138.     DB 079h            ; Bold     Underscored          Inverted
  139.     DB 0F0h            ;               Blinking   Inverted
  140.     DB 0F8h            ; Bold               Blinking   Inverted
  141.     DB 0F1h            ;     Underscored   Blinking   Inverted
  142.     DB 0F9h            ; Bold     Underscored   Blinking   Inverted
  143.  
  144.  
  145. ; Mode change table, used for switching video modes
  146.  
  147. Mode_change_table LABEL BYTE
  148.     DB 2            ; 0  => 2
  149.     DB 3            ; 1  => 3
  150.     DB 2            ; 2  => 2
  151.     DB 3            ; 3  => 3
  152.     DB 3            ; 4  => 3
  153.     DB 2            ; 5  => 2
  154.     DB 2            ; 6  => 2
  155.     DB 7            ; 7  => 7
  156.     DB 8            ; 8  => 8
  157.     DB 9            ; 9  => 9
  158.     DB 0Ah            ; A  => A
  159.     DB 0Bh            ; B  => B
  160.     DB 0Ch            ; C  => C
  161.     DB 3            ; D  => 3
  162.     DB 3            ; E  => 3
  163.     DB 2            ; F  => 2
  164.     DB 3            ; 10 => 3
  165.  
  166.  
  167. ; Dispatch table for Load LEDs (DECLL) routine
  168.  
  169. DECLL_Table LABEL WORD
  170.     DW DECLL_0        ; 0 -- Clear all LEDs
  171.     DW DECLL_1        ; 1 -- Set LED #1
  172.     DW DECLL_2        ; 2 -- Set LED #2
  173.     DW DECLL_3        ; 3 -- Set LED #3
  174.     DW DECLL_4        ; 4 -- Set LED #4
  175.  
  176.  
  177. ; Dispatch table for Erase in Display (ED) routine
  178.  
  179. ED_table LABEL WORD
  180.     DW ED_0            ; 0 -- Clear to end of screen
  181.     DW ED_1            ; 1 -- Clear to beginning of screen
  182.     DW ED_2            ; 2 -- Clear entire screen
  183.  
  184.  
  185. ; Dispatch table for Erase in Line (EL) routine
  186.  
  187. EL_table LABEL WORD
  188.     DW EL_0            ; 0 -- Clear to end of line
  189.     DW EL_1            ; 1 -- Clear to beginning of line
  190.     DW EL_2            ; 2 -- Clear entire line
  191.  
  192.  
  193. ; Dispatch table for Set Graphic Rendition (SGR) routine
  194.  
  195. SGR_Table LABEL WORD
  196.     DW SGR_0        ; 0 -- Clear all renditions
  197.     DW SGR_1        ; 1 -- Bold
  198.     DW SGR_Ignore        ; 2
  199.     DW SGR_Ignore        ; 3
  200.     DW SGR_4        ; 4 -- Underscored
  201.     DW SGR_5        ; 5 -- Blinking
  202.     DW SGR_Ignore        ; 6
  203.     DW SGR_7        ; 7 -- Inverted
  204.  
  205.  
  206. ; Dispatch table for Media Copy (MC) routine
  207.  
  208. MC_Table LABEL WORD
  209.     DW MC_0            ; 0 -- Print screen
  210.     DW MC_1            ; 1 -- Print cursor line
  211.     DW MC_Ignore        ; 2
  212.     DW MC_Ignore        ; 3
  213.     DW MC_4            ; 4 -- Printer controller or Auto Print off
  214.     DW MC_5            ; 5 -- Printer controller or Auto Print on
  215.  
  216.  
  217. ; Strings to be sent for simulated VT100 keys
  218.  
  219. PF1_str DB Esc,'OP',0
  220. PF2_str DB Esc,'OQ',0
  221. PF3_str DB Esc,'OR',0
  222. PF4_str DB Esc,'OS',0
  223.  
  224. ; If cursor keys mode is not set ...
  225.  
  226. Normal_PF7_str DB Esc,'[A',0
  227. Normal_PF8_str DB Esc,'[B',0
  228. Normal_PF9_str DB Esc,'[D',0
  229. Normal_PF10_str DB Esc,'[C',0
  230.  
  231. ; If cursor keys mode is set ...
  232.  
  233. Alternate_PF7_str DB Esc,'OA',0
  234. Alternate_PF8_str DB Esc,'OB',0
  235. Alternate_PF9_str DB Esc,'OD',0
  236. Alternate_PF10_str DB Esc,'OC',0
  237.  
  238. ; As above, but in 7171 mode ...
  239.  
  240. K71_PF1_str DB Esc,'1',0
  241. K71_PF2_str DB Esc,'2',0
  242. K71_PF3_str DB Esc,'3',0
  243. K71_PF4_str DB Esc,'4',0
  244. K71_PF5_str DB Esc,'5',0
  245. K71_PF6_str DB Esc,'6',0
  246. K71_PF7_str DB Esc,'7',0
  247. K71_PF8_str DB Esc,'8',0
  248. K71_PF9_str DB Esc,'9',0
  249. K71_PF10_str DB Esc,'0',0
  250. K71_PF11_str DB Esc,'-',0
  251. K71_PF12_str DB Esc,'=',0
  252. K71_Erase_EOL_str DB Esc,127,0
  253. K71_Home_str DB 8,0
  254. K71_Tab_str DB Esc,Esc,'OC',0
  255. K71_Shift_Tab_str DB Esc,Esc,'OD',0
  256. K71_End_str DB 'J'-100q,0
  257. K71_Del_str DB 127,0
  258. K71_Ins_str DB Esc,'On',0
  259. Null_string DB 0        ; String with no characters
  260.  
  261. ; If keypad application mode is not set ...
  262.  
  263. Num_Zero_str DB '0',0
  264. Num_One_str DB '1',0
  265. Num_Two_str DB '2',0
  266. Num_Three_str DB '3',0
  267. Num_Four_str DB '4',0
  268. Num_Five_str DB '5',0
  269. Num_Six_str DB '6',0
  270. Num_Seven_str DB '7',0
  271. Num_Eight_str DB '8',0
  272. Num_Nine_str DB '9',0
  273. Num_Period_str DB '.',0
  274. Num_Comma_str DB ',',0
  275. Num_Minus_str DB '-',0
  276. Num_Enter_str DB Cr,0
  277.  
  278. ; If keypad application mode is set ...
  279.  
  280. Appl_Zero_str DB Esc,'Op',0
  281. Appl_One_str DB Esc,'Oq',0
  282. Appl_Two_str DB Esc,'Or',0
  283. Appl_Three_str DB Esc,'Os',0
  284. Appl_Four_str DB Esc,'Ot',0
  285. Appl_Five_str DB Esc,'Ou',0
  286. Appl_Six_str DB Esc,'Ov',0
  287. Appl_Seven_str DB Esc,'Ow',0
  288. Appl_Eight_str DB Esc,'Ox',0
  289. Appl_Nine_str DB Esc,'Oy',0
  290. Appl_Period_str DB Esc,'On',0
  291. Appl_Comma_str DB Esc,'Ol',0
  292. Appl_Minus_str DB Esc,'Om',0
  293. Appl_Enter_str DB Esc,'OM',0
  294.  
  295.  
  296. ; Scan codes for keys we have predefined ...
  297.  
  298. Zero_key EQU 82            ; These are all the "keypad" keys
  299. One_key    EQU 79
  300. Two_key    EQU 80
  301. Three_key EQU 81
  302. Four_key EQU 75
  303. Five_key EQU 76
  304. Six_key    EQU 77
  305. Seven_key EQU 71
  306. Eight_key EQU 72
  307. Nine_key EQU 73
  308.  
  309. Period_key EQU 83
  310. Comma_key EQU 55        ; AKA "PrtSc *"
  311. Minus_key EQU 74
  312. Enter_key EQU 78        ; AKA "grey +"
  313.  
  314. PF1_key    EQU 59            ; Use PC's PF keys 1-4 as VT100 PF1-4
  315. PF2_key    EQU 60
  316. PF3_key    EQU 61
  317. PF4_key    EQU 62
  318.  
  319. PF5_key    EQU 63            ; Clone VTERM, takes you to command level
  320. PF6_key    EQU 64            ; As above, takes you to help
  321.  
  322. PF7_key    EQU 65            ; Up-arrow
  323. PF8_key    EQU 66            ; Down
  324. PF9_key    EQU 67            ; Left
  325. PF10_key EQU 68            ; Right ...
  326.  
  327. CtrlPrtSc EQU 114        ; CTRL + */PrtSc keys (set up by BIOS)
  328.  
  329. Scroll_lock_key EQU 70        ; Scroll Lock, aka BREAK
  330. Tab_key    EQU 15            ; Tab key
  331.  
  332.  
  333.     EVEN            ; Try for word boundary
  334.  
  335. ; Dispatch table for keyboard activity
  336.  
  337. Key_codes LABEL WORD
  338.     DW     Zero_key,    One_key,    Two_key
  339.     DW    Three_key,    Four_key,    Five_key
  340.     DW    Six_key,    Seven_key,    Eight_key
  341.     DW    Nine_key,    Period_key,    Comma_key
  342.  
  343.     DW    Minus_key,    Enter_key,    PF1_key
  344.     DW    PF2_key,    PF3_key,    PF4_key
  345.     DW    PF5_key,    PF6_key,    PF7_key
  346.     DW    PF8_key,    PF9_key,    PF10_key
  347.  
  348. Number_of_key_codes EQU ( $ - Key_codes ) / 2
  349.  
  350. Key_actions LABEL WORD
  351.  
  352. Do_Zero_key DW If_keypad_application_mode_set 
  353.     DW Num_Zero_str
  354.     DW Appl_Zero_str
  355.  
  356. Do_One_key DW If_keypad_application_mode_set
  357.     DW Num_One_str
  358.     DW Appl_One_str
  359.  
  360. Do_Two_key DW If_keypad_application_mode_set
  361.     DW Num_Two_str
  362.     DW Appl_Two_str
  363.  
  364. Do_Three_key DW If_keypad_application_mode_set
  365.     DW Num_Three_str
  366.     DW Appl_Three_str
  367.  
  368. Do_Four_key DW If_keypad_application_mode_set
  369.     DW Num_Four_str
  370.     DW Appl_Four_str
  371.  
  372. Do_Five_key DW If_keypad_application_mode_set
  373.     DW Num_Five_str
  374.     DW Appl_Five_str
  375.  
  376. Do_Six_key DW If_keypad_application_mode_set
  377.     DW Num_Six_str
  378.     DW Appl_Six_str
  379.  
  380. Do_Seven_key DW If_keypad_application_mode_set
  381.     DW Num_Seven_str
  382.     DW Appl_Seven_str
  383.  
  384. Do_Eight_key DW If_keypad_application_mode_set
  385.     DW Num_Eight_str
  386.     DW Appl_Eight_str
  387.  
  388. Do_Nine_key DW If_keypad_application_mode_set
  389.     DW Num_Nine_str
  390.     DW Appl_Nine_str
  391.  
  392. Do_Period_key DW If_keypad_application_mode_set
  393.     DW Num_Period_str
  394.     DW Appl_Period_str
  395.  
  396. Do_Comma_key DW If_keypad_application_mode_set
  397.     DW Num_Comma_str
  398.     DW Appl_Comma_str
  399.  
  400. Do_Minus_key DW If_keypad_application_mode_set
  401.     DW Num_Minus_str
  402.     DW Appl_Minus_str
  403.  
  404. Do_Enter_key DW If_keypad_application_mode_set
  405.     DW Num_Enter_str
  406.     DW Appl_Enter_str
  407.  
  408. Do_PF1_key DW Leave_alone
  409.     DW PF1_str
  410.     DW PF1_str
  411.  
  412. Do_PF2_key DW Leave_alone
  413.     DW PF2_str
  414.     DW PF2_str
  415.  
  416. Do_PF3_key DW Leave_alone
  417.     DW PF3_str
  418.     DW PF3_str
  419.  
  420. Do_PF4_key DW Leave_alone
  421.     DW PF4_str
  422.     DW PF4_str
  423.  
  424. Do_PF5_key DW Leave_emulator
  425.     nop
  426.     nop
  427.     nop
  428.     nop
  429.  
  430. Do_PF6_key DW Call_Helper
  431.     nop
  432.     nop
  433.     nop
  434.     nop
  435.  
  436. Do_PF7_key DW If_cursor_keys_mode_set
  437.     DW Normal_PF7_str
  438.     DW Alternate_PF7_str
  439.  
  440. Do_PF8_key DW If_cursor_keys_mode_set
  441.     DW Normal_PF8_str
  442.     DW Alternate_PF8_str
  443.  
  444. Do_PF9_key DW If_cursor_keys_mode_set
  445.     DW Normal_PF9_str
  446.     DW Alternate_PF9_str
  447.  
  448. Do_PF10_key DW If_cursor_keys_mode_set
  449.     DW Normal_PF10_str
  450.     DW Alternate_PF10_str
  451.  
  452.  
  453. ; Alternate dispatch table for keyboard activity
  454.  
  455. Key_codes_2 LABEL WORD
  456.     DW     Two_key,        Four_key,    Six_key
  457.     DW    Eight_key
  458.  
  459. Number_of_key_codes_2 EQU ( $ - Key_codes_2 ) / 2
  460.  
  461. Key_actions_2 LABEL WORD
  462.  
  463. Do_Two_key_2 DW If_cursor_keys_mode_set
  464.     DW Normal_PF8_str
  465.     DW Alternate_PF8_str
  466.  
  467. Do_Four_key_2 DW If_cursor_keys_mode_set
  468.     DW Normal_PF9_str
  469.     DW Alternate_PF9_str
  470.  
  471. Do_Six_key_2 DW If_cursor_keys_mode_set
  472.     DW Normal_PF10_str
  473.     DW Alternate_PF10_str
  474.  
  475. Do_Eight_key_2 DW If_cursor_keys_mode_set
  476.     DW Normal_PF7_str
  477.     DW Alternate_PF7_str
  478.  
  479.  
  480. ; Other alternate dispatch table for IBM 7171 keyboard activity
  481.  
  482. Key_codes_7171 LABEL WORD
  483.     DW     Zero_key,    One_key,    Two_key
  484.     DW    Three_key,    Four_key,    Five_key
  485.     DW    Six_key,    Seven_key,    Eight_key
  486.     DW    Nine_key,    Period_key,    Comma_key
  487.  
  488.     DW    Minus_key,    Enter_key,    PF1_key
  489.     DW    PF2_key,    PF3_key,    PF4_key
  490.     DW    PF5_key,    PF6_key,    PF7_key
  491.     DW    PF8_key,    PF9_key,    PF10_key
  492.  
  493.     X EQU (alt_shift * 256)
  494. ;  X is the alt_shift flag shifted into the left half
  495.  
  496. ; 104 and 105 are scan codes for ALT F1 and ALT F2
  497.  
  498.     DW    X+104,    X+105
  499.  
  500. ;  120, 121 etc. are scan codes for top row digits 1 .. 0 followed by - and =
  501.  
  502.     DW    X+120,        X+121,        X+122
  503.     DW    X+123,        X+124,        X+125
  504.     DW    X+126,        X+127,        X+128
  505.     DW    X+129,        X+130,        X+131
  506.  
  507.     DW    Tab_key
  508.     DW    (left_shift * 256) + Tab_key
  509.     DW    14        ; Backarrow
  510.  
  511. Number_of_key_codes_7171 EQU ( $ - Key_codes_7171 ) / 2
  512.  
  513. Key_actions_7171 LABEL WORD
  514.     DW    K71_Ins_str    ; 0 (Ins) on numeric pad
  515.     DW    K71_End_str    ; 1
  516.     DW    Alternate_PF8_str ; 2 (down)
  517.     DW    Null_string    ; 3
  518.     DW    Alternate_PF9_str ; 4 (left)
  519.     DW    Null_string    ; 5
  520.     DW    Alternate_PF10_str ; 6 (right)
  521.     DW    K71_Home_str    ; 7
  522.     DW    Alternate_PF7_str ; 8 (up)
  523.     DW    Null_string    ; 9
  524.     DW    K71_Del_str    ; period (Del)
  525.     DW    Null_string    ; Comma (PrtSc)
  526.     DW    K71_Erase_EOL_str ; Grey -
  527.     DW    Appl_Enter_str    ; Grey +
  528.     DW    K71_PF1_str    ; F1
  529.     DW    K71_PF2_str
  530.     DW    K71_PF3_str
  531.     DW    K71_PF4_str
  532.     DW    K71_PF5_str
  533.     DW    K71_PF6_str
  534.     DW    K71_PF7_str
  535.     DW    K71_PF8_str
  536.     DW    K71_PF9_str
  537.     DW    K71_PF10_str    ; F10
  538.     DW    K71_PF11_str    ; F11
  539.     DW    K71_PF12_str    ; F12
  540.     DW    K71_PF1_str    ; F1 again (on top row this time)
  541.     DW    K71_PF2_str
  542.     DW    K71_PF3_str
  543.     DW    K71_PF4_str
  544.     DW    K71_PF5_str
  545.     DW    K71_PF6_str
  546.     DW    K71_PF7_str
  547.     DW    K71_PF8_str
  548.     DW    K71_PF9_str
  549.     DW    K71_PF10_str    ; F10
  550.     DW    K71_PF11_str    ; F11
  551.     DW    K71_PF12_str    ; F12 (end of top row)
  552.     DW    K71_Tab_str
  553.     DW    K71_Shift_Tab_str
  554.     DW    Alternate_PF9_str ; Backarrow, usually DELete, now = left arrow
  555.  
  556.  
  557. ; Table of max per-loop character counts based on baud rate
  558.  
  559. Baud_Char LABEL WORD
  560.     DW 1            ; 45.5 baud    1
  561.     DW 1            ;   50         2         
  562.     DW 1            ;   75         3
  563.     DW 1            ;  110         4
  564.     DW 2            ;  135         5
  565.     DW 3            ;  150         6
  566.     DW 5            ;  300         7
  567.     DW 10            ;  600         8
  568.     DW 20            ; 1200         9
  569.     DW 30            ; 1800         10
  570.     DW 33            ; 2000         11
  571.     DW 41            ; 2400         12
  572.     DW 82            ; 4800         13
  573.     DW 164            ; 9600 baud, enough for two full lines    14
  574.     DW 164            ; 19200 baud                              15
  575.     DW 164            ; 23040 baud                  16
  576.     DW 164            ; 38400 baud                  17
  577.  
  578. Baud_table_size EQU 17        ; Number of baud rates known
  579.  
  580.  
  581. ; Maximum number of scrolls to do in a display cycle
  582.  
  583.     PUBLIC Maximum_scrolls
  584.  
  585. Maximum_scrolls DW 1
  586.  
  587.  
  588. ; Strings sent in response to incoming escape sequences
  589.  
  590. DA_str    DB Esc,'[?1;2c',0    ; Standard answer (for VT100 with AVO) to
  591.                 ;  Device Attributes (DA)
  592.  
  593. ;DA_str    DB Esc,'[?6c',0        ; Standard answer (for VT102) to
  594.                 ;  Device Attributes (DA)
  595.  
  596. DSR_str    DB Esc,'[0n',0        ; The No Malfunctions answer to Device
  597.                 ;  Status Request (DSR)
  598.  
  599. CPR_str    DB Esc,'[',0        ; First two chars in CPR esc seq
  600.  
  601. Ident_str DB Esc,'[?99c',0    ; Code to say that we are not just a VT100
  602.  
  603. No_memory DB Cr, Lf, '? Not enough memory for Terminal Emulation', Cr, Lf, '$'
  604.  
  605. Lc    DB ' lc '        ; For lower case
  606. CAPS    DB 'CAPS'        ; Caps lock
  607. Arrow    DB 24,25,27,26        ; Up, down, left, right
  608. Num    DB 'NumL'        ; Num lock
  609.  
  610.  
  611. ; Table to translate graphic mode VT100 char into "best" IBM PC equivalent
  612.  
  613. Graphic_translation_table LABEL BYTE
  614.  
  615.     DB 032            ; 95
  616.     DB 004            ; 96
  617.     DB 176            ; 97
  618.     DB 029            ; 98
  619.     DB 023            ; 99
  620.     DB 017            ; 100
  621.     DB 025            ; 101
  622.     DB 248            ; 102
  623.     DB 241            ; 103
  624.     DB 174            ; 104
  625.     DB 018            ; 105
  626.     DB 217            ; 106
  627.     DB 191            ; 107
  628.     DB 218            ; 108
  629.     DB 192            ; 109
  630.     DB 197            ; 110
  631.     DB 196            ; 111
  632.     DB 196            ; 112
  633.     DB 196            ; 113
  634.     DB 196            ; 114
  635.     DB 196            ; 115
  636.     DB 195            ; 116
  637.     DB 180            ; 117
  638.     DB 193            ; 118
  639.     DB 194            ; 119
  640.     DB 179            ; 120
  641.     DB 243            ; 121
  642.     DB 242            ; 122
  643.     DB 227            ; 123
  644.     DB 247            ; 124
  645.     DB 156            ; 125
  646.     DB 250            ; 126
  647.  
  648.  
  649. ; Mode line templates -- attribute byte followed by string followed by
  650. ;  NUL character (ASCII 0) -- two NULs in a row mark end-of-template
  651.  
  652. Mode_template LABEL BYTE    ; Mode line
  653.  
  654. ;    DB 70h,Space,Space,0
  655. ;    DB 71h,'F5',0,70h,'=Command mode',Space,Space,Space,0
  656. ;    DB 71h,'F6',0,70h,'=Help    Esc chr=',0,71h
  657.     DB 70h, ' '
  658.     VerDef
  659.     DB '   ',0
  660.     DB 71h,'ALT-F6',0
  661.     DB 70h,'=Help     Esc chr=',0,71h
  662. M_Esc    DB '^[',0,70h,Space,Space,Space,Space,0
  663. M_Prt    DB 70h,'   ',0
  664.   M_Prt_length=$-M_Prt        ; Length of this item
  665.     DB 70h,Space,Space,Space,Space,0,71h
  666. M_Caps    DB ' lc ',0,70h,Space,Space,Space,0,71h
  667. M_KPad    DB 24,25,27,26,0
  668.     DB 70h,Space,Space,Space,Space,0
  669. M_L1    DB 70h,'L1',0,70h,Space,0
  670. M_L2    DB 70h,'L2',0,70h,Space,0
  671. M_L3    DB 70h,'L3',0,70h,Space,0
  672. M_L4    DB 70h,'L4',0,70h,Space,Space,0
  673.     DB 0
  674.  
  675. M_Prt_On  DB 71h,'Prt',0
  676. M_Prt_Off DB 70h,'   ',0
  677.  
  678. ; Template for "mode line" after user has hit the escape char
  679.  
  680. Esc_chr_template LABEL BYTE
  681.  
  682.     DB 70h,Space,0
  683.     DB 71h,'?',0,70h,'=Help',Space,Space,Space,Space,0
  684.     DB 71h,'C',0,70h,'=Close',Space,Space,Space,Space,0
  685.     DB 71h,'S',0,70h,'=Status',Space,Space,Space,Space,0
  686.     DB 71h,'B',0,70h,'=send Break',Space,Space,Space,0
  687.     DB 71h,'M',0,70h,'=Mode line',Space,Space,Space,Space,0
  688.     DB 71h,'?',0,70h,' for full list',Space,0,0
  689.  
  690. offmsg    DB 'Off'
  691. onmsg    DB 'On '
  692.  
  693.     EVEN            ; Try for word boundary
  694.  
  695. beldiv    DW 2DCh            ; 550 hz?
  696.  
  697.  
  698. ; Vt100 data, changeable ...
  699.  
  700. ; Screen addressing data
  701.  
  702.     PUBLIC Max_number_of_chars, Number_of_chars_done, Image_ptr
  703.  
  704. Max_number_of_chars DW 10    ; Max number of chars to do in Do_Screen
  705. Number_of_chars_done DW 0    ; How many chars we have done this pass
  706.  
  707. Number_of_scrolls_done DW 0    ; Count of lines scrolled this display cycle
  708.  
  709. Image_ptr DW ?            ; Pointer to screen image, used by Put_Screen
  710.  
  711.  
  712. ; VT100 status flags and flag word
  713.  
  714. Keypad_application_mode EQU 1    ; Determines data sent by keypad keys
  715. Cursor_keys_mode EQU 2        ; Determines data sent by arrow keys
  716. Private_esc_seq EQU 4        ; A q-mark was found in esc seq
  717. Printer_controller_mode EQU 8    ; Send all data to printer, not display
  718. Auto_copy_mode EQU 10h        ; Send data to display AND printer
  719.  
  720. Printer_wanted = Printer_controller_mode + Auto_copy_mode
  721.  
  722. VT100_status_flags DB 0        ; Place to hold status flags
  723. Old_status_flags DB 0        ; Place to hold previous value
  724.  
  725.  
  726. ; Screen management flags
  727.  
  728. Screen_open EQU 1        ; Command mode screen has already been saved
  729. Position_changed EQU 2        ; New position
  730. Line_changed EQU 4        ; Data on current line changed
  731. Screen_changed EQU 8        ; Data on more than one line changed
  732. Force_screen_update EQU 10h    ; Update every character of both video pages,
  733.                 ;  (on color card), which is slower than
  734.                 ;  mollasses in January
  735.  
  736. Changed EQU Position_changed + Line_changed + Screen_changed
  737.  
  738. Screen_flags DB 0        ; Flags for managing the screen
  739.  
  740. Hit_ESC    DB 0            ; Flag to say we just hit an escape, used only
  741.                 ;  while in printer controller mode
  742.  
  743. Prev_shift_state DB 0FFh    ; Set initial shift to something impossible
  744.  
  745.  
  746. ; Rendition / attribute data ...
  747.  
  748. Bold    EQU 1            ; Extra bright (SGR code 1)
  749. Underscored EQU 2        ; Underlined (SGR code 4)
  750. Blinking EQU 4            ; Blinking (SGR code 5)
  751. Inverted EQU 8            ; Inverse video (SGR code 7)
  752. Graphi    EQU 10h            ; Flag for graphics char set
  753.  
  754. Rendition DB ?            ; Currently set graphic rendition flags
  755. Attribute_Byte DB ?        ; Current attribute
  756.  
  757.  
  758. ; VT100 LEDs L1 - L4
  759.  
  760. LED1    EQU 1
  761. LED2    EQU 2
  762. LED3    EQU 4
  763. LED4    EQU 8
  764.  
  765. LEDs    DB 0            ; Start with all four LEDs off
  766.  
  767. LoWork    DB 10 DUP (Space)    ; Low level work area, bigger than needed
  768.  
  769.  
  770. ; Scrolling region
  771.  
  772. Top_margin DB ?            ; Offset of top line in scrolling region
  773. Bottom_margin DB ?        ; Offset of bottom line in scrolling region
  774.  
  775.  
  776.     EVEN            ; Try for word boundary
  777.  
  778. Script_processor DW 0        ; Address of script processor to run
  779.  
  780. Line_Ptr DW ?            ; Address of first char on line we are on
  781. Char_Ptr DW ?            ; Address of the char we are on
  782.  
  783. Previous_char    DB ?        ; Most recently seen char
  784. Backed_up_char    DB ?        ; backed-up char
  785.  
  786. Char_set DB ?            ; Character set we are in
  787. G0_set    DB ?            ; G0 character set
  788. G1_set    DB ?            ; G1 character set
  789.  
  790. ; One byte of quickly-clobbered junk, terminated with $ just-in-case
  791.  
  792. Tmp    DB ?, '$'
  793.  
  794. ; Things saved by DECSC and restored by DECRC
  795.  
  796. Save_char_set DB ?        ; Saved char set number
  797. Save_G0_set DB ?        ; Saved G0 char set
  798. Save_G1_set DB ?        ; Saved G1 char set
  799. Save_rendition DB ?        ; Saved rendition
  800. Save_position DW ?        ; Saved cursor position
  801.  
  802.  
  803. ; Another saved item ...
  804.  
  805. Save_SP_for_abort DW ?        ; Place to save a stack ptr
  806.  
  807.  
  808.     EVEN            ; Try for word boundary
  809.  
  810. ; Numbers read in during an escape sequence
  811.  
  812. NumCnt    DB ?            ; The count of numbers we have stored
  813. NumPtr    DB ?            ; Which one we are on
  814. Nums    DB 10 DUP (?)        ; Numbers we have seen ...
  815.  
  816. EBufLn    EQU 128
  817. EBuffr    DB EBufLn DUP (?)    ; Escape buffer
  818. EBufGt    DW ?            ; Get ptr
  819. EBufPt    DW ?            ; Put ptr
  820. EBufCt    DB ?            ; Count of chars in buffer
  821.  
  822. NewRow    DB ?            ; Place to put new row number
  823.  
  824. ; Key redefinitions
  825.  
  826. ktrntab    DW ?            ; address of translation table
  827. krpltab    DW ?            ; address of replacement table
  828. ktlen    DW ?
  829.  
  830. captrtn    DW ?            ; Routine to call for captured output
  831.  
  832. portno    DB ?            ; Port number
  833.  
  834. flags    DB ?            ; status flags, our copy of [bx].flg
  835.  
  836. ; Things in flags1 ...
  837.  
  838. prtscr    EQU 80h            ; print screen pressed
  839. lnwrap    EQU 40h            ; line wrap enabled
  840. inited    EQU 08h            ; been here before...
  841.  
  842. flags1    DB 0            ; internal flags
  843.  
  844. Esc_Ch    DB ?
  845. argadr    DW ?            ; address of arg blk
  846.  
  847.     PUBLIC Cursor_position
  848.  
  849. Cursor_position    LABEL WORD    ; Single name for both Column and Row
  850. Column    DB ?            ; Column we are in
  851. Row    DB ?            ; Row we are on
  852.  
  853. Cursor    DW ?            ; Working place for Cursor pos
  854.  
  855. DataS    ENDS
  856.  
  857.  
  858. ; Dummy segment for allocated memory
  859.  
  860. Alloc    SEGMENT AT 0
  861.  
  862. ;***************************************************************************
  863. ; The screen image, locally updated then blasted out to real screen memory
  864. ;***************************************************************************
  865.  
  866. Number_of_rows EQU 24        ; Length in rows
  867. Number_of_columns EQU 80    ; Width in characters
  868. Highest_row EQU Number_of_rows-1; Highest row number
  869. Highest_column EQU Number_of_columns-1 ; Highest column number
  870. Lower_right EQU (100h*Highest_row) + Highest_column
  871.                 ; Lower right corner of virtual screen ...
  872. Number_of_chars_on_VT100_screen EQU Number_of_columns*Number_of_rows
  873.                 ; Number of chars in a VT100 screen
  874. Number_of_rows_PC EQU 25    ; Length in rows including mode line
  875. Number_of_chars_on_PC_screen EQU Number_of_columns*Number_of_rows_PC
  876.                 ; Number of chars in IBM screen
  877.  
  878.     EVEN            ; Try for word boundary
  879.  
  880. ; Display update list
  881.  
  882.     PUBLIC Update_list
  883.  
  884. Update_list DW (2 * Number_of_chars_on_PC_screen) DUP (?) ; One word location
  885.                 ;  info followed by one word of char/attr
  886.                 ;  for each update item
  887.  
  888. Alloc_cursor_position DW ?    ; Copy of current cursor position
  889.  
  890.     PUBLIC Screen_Image, Mode_line
  891.  
  892. Screen_Image DW Number_of_chars_on_VT100_screen DUP (?)
  893.                 ; The screen buffer itself
  894.  
  895. ; Mode line, follows immediately after screen image
  896.  
  897. Mode_line DW Number_of_columns DUP (?)
  898.  
  899.  
  900. ; The previous screen contents, used to build update list
  901.  
  902. Old_Image DW Number_of_chars_on_PC_screen DUP (?)
  903.  
  904.  
  905. ; Contents of screen on entry to terminal emulator, restored on exit
  906.  
  907. Command_mode_cursor DW ?    ; Saved cursor position from command mode
  908. Command_mode_screen DW Number_of_chars_on_PC_screen DUP (?)
  909.  
  910. End_Alloc LABEL BYTE
  911.  
  912. Alloc    ENDS
  913.  
  914. ;***************************************************************************
  915.  
  916.  
  917. ; *Code* ...
  918.  
  919. RetSkp    MACRO            ; Return skip
  920.     jmp RSkp
  921.     ENDM
  922.  
  923. RetNop    MACRO            ; Return from subroutine, take up 3 bytes
  924.      ret
  925.      nop
  926.      nop
  927.     ENDM
  928.  
  929.  
  930. Code    SEGMENT PUBLIC        ; code segment
  931.  
  932.     EXTRN Quit_emulator:BYTE, Which_card:BYTE
  933.     EXTRN PrtChr_PC:NEAR, OutChr_PC:NEAR, SendBr:NEAR, Helper:NEAR
  934.     EXTRN SerIni_PC:NEAR, SerRst_PC:NEAR, Enter_Server:NEAR
  935.     EXTRN Exit2:NEAR, Type_to_screen:NEAR, Force_card:BYTE
  936.     EXTRN PosCur_PC:NEAR, Quick_Push:NEAR, ClrMod_PC:NEAR
  937.     EXTRN Get_memory_block:NEAR, Set_up_video_card_pointers:NEAR
  938.     EXTRN Go_to_page_zero:NEAR, Blank_current_page:NEAR
  939.     EXTRN Switch_video_pages:NEAR, Beam_Off:NEAR, Beam_On:NEAR
  940.  
  941. Datas_ds DW 0            ; Place to hold normal ds (DATAS)
  942. Alloc_ds DW 0            ; Place to hold ptr to allocated ds (ALLOC)
  943.  
  944. Screen_Image_ptr DD 0        ; Doubleword pointer to VT100 image
  945. Mode_Line_ptr DD 0        ; Doubleword pointer to mode line
  946.  
  947. Max_number_of_items DW 300    ; Max number of display update items to do
  948.                 ;  during retrace in Update_nondisplayed_page
  949. Number_of_update_items DW 0    ; How many items in list?
  950.  
  951.  
  952.     ASSUME cs:Code, ds:Datas, es:Datas
  953.  
  954.  
  955. ; Close out terminal emulation screen
  956.  
  957. Close_Screen_PC PROC
  958.  
  959.     test Screen_flags, Screen_Open ; Should we restore?
  960.      jz CLO_ret        ;  No
  961.  
  962.     call Restore_command_mode_screen ; Get back original screen
  963.     and Screen_flags, NOT Screen_open ; Clear this flag
  964.  
  965. CLO_ret:
  966.     ret            ; Done here
  967.  
  968. Close_Screen_PC ENDP
  969.  
  970.  
  971. ; Perform terminal emulation
  972.  
  973. Term_PC    PROC            ; terminal emulator entry point
  974.  
  975.     push es            ; save caller's extra segment address
  976.  
  977.     mov argadr, ax        ; save argument ptr
  978.  
  979.     mov ax, SEG datas
  980.     mov es, ax
  981.  
  982.     call Set_up_dynamic_memory ; Try to get memory
  983.      jnc TRM_0
  984.  
  985.     mov ah, PrStr        ; Code to type message
  986.     mov dx, OFFSET No_memory ; Complain about lack of memory
  987.     int Dos            ; Display it
  988.  
  989.     mov Quit_emulator, 1    ; Flag that we want out
  990.     jmp TRM_S3        ; Quit the program
  991.  
  992. TRM_0:    call argini        ; Initialize options from arg address
  993.     call Enter_text_mode    ; This program requires text mode
  994.  
  995.     call Set_up_video_card_pointers ; Learn video mode, card type, etc.
  996.  
  997.     test Screen_flags, Screen_open ; Is the screen already "open"?
  998.      jnz TRM_2        ;  All set, don't worry
  999.  
  1000.     call Save_command_mode_screen ; Save it
  1001.     or Screen_flags, Screen_open ; Set flag for later
  1002.  
  1003. TRM_2:    test flags1, inited    ; Have we run yet?
  1004.      jz TRM_3        ;  No, go initialize everything
  1005.  
  1006.     call ReInit_Screen    ; Display our screen buffer on the screen
  1007.     jmp SHORT TRM_5        ; Join common code
  1008.  
  1009. TRM_3:    call Initialize_Screen    ; Initialize screen and buffers
  1010.     call Flush_esc_buffer    ; Initialize pointers into escape buffer
  1011.     call Do_mode_line    ; Do proper thing with the mode line
  1012.     call Do_our_screen    ; Get screen up-to-date
  1013.     or flags1, inited    ; Remember that we've done this already
  1014.     
  1015. TRM_5:    mov Quit_emulator, 0    ; Clear this flag
  1016.  
  1017.  
  1018. ; First, try for chars from keyboard
  1019.  
  1020.     PUBLIC Trm_Kb
  1021.  
  1022. TRM_Kb:
  1023.  
  1024. ; Before we are allowed to really check the keyboard, we have to see if
  1025. ;  we are running under control of a script.  If we are, we have to call
  1026. ;  it at its "keyboard" entry instead of reading from the keyboard.
  1027.  
  1028.     cmp Script_processor, 0    ; Is there a script processor to run?
  1029.      je TRM_No_script    ;  No
  1030.  
  1031. TRM_Ck:    mov ah, 1        ; Code to see if anything there
  1032.     int Kb            ; Check input buffer
  1033.      jnz TRM_S0        ;  Get char
  1034.  
  1035.     mov al, 0FFh        ; Say we don't have a character
  1036.     jmp SHORT TRM_S1    ; Pass this along to the processor
  1037.  
  1038. TRM_S0:    sub ah, ah        ; Code zero
  1039.     int Kb            ; Get the char from the buffer
  1040.  
  1041. TRM_S1:    sub ah, ah        ; Code for "keyboard" entry
  1042.     call Script_processor    ; Let it do its thing
  1043.     test Quit_emulator, 1    ; Is this flag set?
  1044.      jz TRM_Scr        ;  No, try for more keyboard chars ...
  1045.  
  1046. TRM_S3:    call Close_Screen_PC    ; Go set things up right for command mode
  1047.     jmp SHORT TRM_Quit    ; Go back to other program
  1048.  
  1049. TRM_No_script:
  1050.     mov ah, 1        ; Code to see if anything there
  1051.     int Kb            ; Check ...
  1052.      jz Trm_Scr        ; nothing available...
  1053.  
  1054.     sub ah, ah        ; Code zero
  1055.     int Kb            ; get the char from the buffer
  1056.  
  1057.     push ax            ; save character temporarily
  1058.     call GSS        ; get shift state into al
  1059.     mov bl, al        ; save shift state
  1060.     pop ax
  1061.  
  1062.     cmp al, Esc_Ch        ; Escape character?
  1063.      jne TRM_Key        ;  No, go deal with the character
  1064.  
  1065.     mov si, OFFSET Esc_chr_template ; The template giving help for
  1066.                 ;  the escape char
  1067.     call Build_mode_line    ; Turn it into a mode line
  1068.     call Do_our_screen    ; Display it
  1069.     jmp SHORT TRM_Quit    ; Go finish up here
  1070.  
  1071. TRM_Key:
  1072.     call Handle_keystroke    ; Do whatever is required for this keystroke
  1073.  
  1074.     test Quit_emulator, 1    ; Is this flag set?
  1075.      jz TRM_Kb        ;  No, try for more keyboard chars ...
  1076.  
  1077.     call Close_Screen_PC    ; Go set things up right for command mode
  1078.     jmp TRM_Quit        ; Go back to other program
  1079.  
  1080.  
  1081. ; Second, handle any buffered port characters
  1082.  
  1083.     PUBLIC TRM_Scr
  1084.  
  1085. TRM_Scr:
  1086.     call Do_Screen        ; Call routine to process all buffered
  1087.                 ;  characters received over the comm port
  1088.     test Quit_emulator, 1    ; Is this flag set?
  1089.      jz TRM_Kb        ;  No, try for more keyboard chars ...
  1090.  
  1091.     call Close_Screen_PC    ; Go set things up right for command mode
  1092. ;    jmp TRM_Quit        ; Go back to other program
  1093.  
  1094.  
  1095. ; User hit the magic character, leave this routine to see what he wants
  1096.  
  1097. TRM_Quit:
  1098.     call Go_to_page_zero    ; Be on page zero in display memory
  1099.  
  1100.     cmp Script_processor, 0    ; Is there a script processor active?
  1101.      je TRM_q_no_script    ;  No
  1102.  
  1103.     mov ah, 2        ; Code to shutdown
  1104.     call Script_processor    ; Shut him down
  1105.  
  1106. TRM_q_no_script:
  1107.     mov al, flags
  1108.     mov bx, argadr
  1109.     mov [bx].flgs, al    ; update flags in arg block
  1110.     pop es            ; restore segment register
  1111.  
  1112.     ret            ; and return to caller
  1113.  
  1114. Term_PC    ENDP
  1115.  
  1116.  
  1117. ; Initialize internal variables based on argument block we were passed
  1118.  
  1119. argini    PROC            ; read passed arguments
  1120.  
  1121.     mov bx, argadr        ; base of argument block
  1122.     mov al, [bx].flgs    ; get flags
  1123.     and al, capt + havtt + lclecho + modoff
  1124.     mov flags, al        ; mask for allowable and save
  1125.  
  1126.     mov al, [bx].prt
  1127.     mov portno, al        ; update port number
  1128.  
  1129.     mov ax, [bx].captr
  1130.     mov captrtn, ax        ; buffer capture routine
  1131.  
  1132.     mov ax, [bx].belld
  1133.     mov beldiv, ax        ; bell divisor
  1134.  
  1135.     mov ax, [bx].klen
  1136.     mov ktlen, ax        ; length of key redef tbl
  1137.  
  1138.     mov ax, [bx].ktab
  1139.     mov ktrntab, ax        ; save key translation table
  1140.  
  1141.     mov ax, [bx].krpl
  1142.     mov krpltab, ax
  1143.  
  1144.     mov al, [bx].escc
  1145.     mov Esc_ch, al
  1146.  
  1147.     mov ax, 4        ; Get a 4
  1148.     mov Max_number_of_chars, ax ; Store it as default
  1149.  
  1150.     mov al, [bx].BaudB    ; Get baud bits
  1151.     cmp al, Baud_table_size    ; Too big?
  1152.      jnb ARG_1        ;  Yes, use the default
  1153.  
  1154.     shl al, 1        ; Double for word offset
  1155.     cbw            ; Make full word
  1156.     mov bx, ax        ; Copy to bx
  1157.     mov ax, Baud_Char[bx]    ; Pick up the value for this baud rate
  1158.     mov Max_number_of_chars, ax ; Install as the per-loop limit
  1159.                 ;  in Do_Screen
  1160.  
  1161. ARG_1:    ret            ; That's it
  1162.  
  1163. argini    ENDP
  1164.  
  1165.  
  1166. Set_up_dynamic_memory PROC
  1167.  
  1168.     cmp Alloc_ds, 0        ; Is this already set up?
  1169.      jnz SDM_OK        ;  Yes, don't do another
  1170.  
  1171.     mov bx, OFFSET End_Alloc+15 ; Round up to next paragraph
  1172.     mov cl, 4        ; Shift count
  1173.     shr bx, cl        ; Shift to get number of paras we need
  1174.  
  1175.     call Get_memory_block    ; Get a memory block of the right size
  1176.      jc SDM_ret        ;  NG, die
  1177.  
  1178.     mov Alloc_ds, ax    ; Save the address of our block
  1179.  
  1180.     mov WORD PTR Screen_Image_ptr+2, ax ; Save it here also ...
  1181.     mov WORD PTR Mode_Line_ptr+2, ax ;  and here ...
  1182.  
  1183.     mov ax, OFFSET Screen_Image ; Offset of the screen image in its seg
  1184.     mov WORD PTR Screen_Image_ptr, ax ; Save for other users
  1185.  
  1186.     mov ax, OFFSET Mode_Line ; Offset of the mode line
  1187.     mov WORD PTR Mode_Line_ptr, ax ; Save it also
  1188.  
  1189.     mov ax, Datas        ; Get ptr to DataS segment
  1190.     mov Datas_ds, ax    ; Save it here
  1191.  
  1192. SDM_OK:    clc            ; No error
  1193.  
  1194. SDM_ret: ret
  1195.  
  1196. Set_up_dynamic_memory ENDP
  1197.  
  1198.  
  1199. ; Initialize internal screen buffer to blanks, put cursor in upper
  1200. ;  left corner of screen
  1201.  
  1202.     PUBLIC Initialize_screen, Rendition, Screen_flags
  1203.  
  1204. Initialize_Screen PROC        ; init screen stuff
  1205.  
  1206. VTFlags = Keypad_application_mode + Cursor_keys_mode
  1207.  
  1208.     and VT100_status_flags, NOT VTFlags ; Turn off all relevant flags
  1209.  
  1210.     sub al, al        ; Get a zero
  1211.     mov Char_set, al    ; In char set 0
  1212.     mov G0_set, al        ; This set is non-graphics
  1213.     mov G1_set, al        ; This set is non-graphics also
  1214.     mov Rendition, al    ; Normal rendition
  1215.     mov Attribute_Byte, 7    ; Normal screen attribute (white on black)
  1216.  
  1217.     mov Top_margin, al    ; Zero top of scrolling region
  1218.     mov al, Highest_row    ; Get number of highest row on VT100 screen
  1219.     mov Bottom_margin, al    ; Save as bottom of scrolling region
  1220.  
  1221.     mov ax, Alloc_ds    ; Ptr to allocated data segment
  1222.     mov es, ax        ; Load into es
  1223.     ASSUME es:Alloc
  1224.  
  1225.     cld            ; Move forward
  1226.  
  1227.     mov ax, 0720h        ; Normal video blank
  1228.     mov cx, Number_of_chars_on_PC_screen ; Number of bytes to lay down
  1229.     mov di, OFFSET Screen_Image ; Where to put the bytes
  1230.     rep stosw        ; Zap the buffer
  1231.  
  1232.     mov cx, Number_of_chars_on_PC_screen ; Number of bytes to lay down
  1233.     mov di, OFFSET Old_Image ; Where to put the bytes
  1234.     rep stosw        ; Zap the buffer
  1235.  
  1236.     mov ax, Datas_ds    ; Ptr to normal data segment
  1237.     mov es, ax        ; Load into es
  1238.     ASSUME es:Datas
  1239.  
  1240.     cmp cs:Which_card, 1    ; Color card?
  1241.      jne ISC_2        ;  Nope, skip this
  1242.  
  1243.     call Blank_current_page    ; Clear page zero
  1244.     call Switch_video_pages    ; Switch to the other page
  1245.     call Blank_current_page    ; Clear page one
  1246.     call Switch_video_pages    ; Switch back to the first page
  1247.  
  1248. ISC_2:    sub ax, ax        ; Make a zero
  1249.     mov Cursor_position, ax    ; Store as cursor position
  1250.     jmp Set_pointers    ; Go set up ptrs, return from there
  1251.  
  1252. Initialize_Screen ENDP
  1253.  
  1254.  
  1255. ; Re-initialize screen ... we have run this module before, but the
  1256. ;  screen needs to be fully restored
  1257.  
  1258.     PUBLIC ReInit_Screen
  1259.  
  1260. ReInit_Screen PROC        ; init screen stuff
  1261.  
  1262.     mov ax, Alloc_ds    ; Ptr to allocated segment
  1263.     mov ds, ax        ; Set ds to it
  1264.      nop            ;  Be nice to debugger
  1265.     mov es, ax        ; es also
  1266.     ASSUME ds:Alloc, es:Alloc
  1267.  
  1268.     mov si, OFFSET Screen_Image
  1269.     mov di, OFFSET Old_Image
  1270.     mov cx, Number_of_chars_on_PC_screen
  1271.     cld            ; Forwards
  1272.     rep movsw        ; Force old image to match the screen
  1273.  
  1274.     mov ax, Datas_ds    ; Ptr to allocated segment
  1275.     mov ds, ax        ; Set ds to it
  1276.      nop            ;  Be nice to debugger
  1277.     mov es, ax        ; es also
  1278.     ASSUME ds:Datas, es:Datas
  1279.  
  1280.     call Do_Mode_Line    ; Make sure mode line is up-to-date
  1281.     call Set_up_video_card_pointers ; Adapt to the current card
  1282.  
  1283.     call Beam_Off        ; Suppress video during copy of screen
  1284.     mov si, OFFSET Screen_Image ; Source OFFSET within segment
  1285.     sub di, di        ; Start at zero
  1286.     mov cx, Number_of_chars_on_PC_screen ; Full PC screen
  1287.     push es            ; Save reg
  1288.     ASSUME es:Nothing
  1289.     call Get_Screen_Segment ; Get address of our screen
  1290.     mov es, ax        ; Install it
  1291.  
  1292.     mov ax, Alloc_ds    ; Segment that holds the Screen_Image
  1293.     mov ds, ax        ;  which we must copy from
  1294.     ASSUME ds:Alloc
  1295.  
  1296.     cld            ; Forwards
  1297.     rep movsw        ; Blast out the screen
  1298.     pop es            ; Get back reg
  1299.     ASSUME es:Datas
  1300.  
  1301.     mov ax, Datas_ds    ; Normal segment
  1302.     mov ds, ax        ; Restore it
  1303.     ASSUME ds:Datas
  1304.  
  1305.     call Beam_On        ; Re-enable video
  1306.     mov ah, 2        ; Code to set cursor position
  1307.     sub bh, bh        ; Page zero
  1308.     mov dx, Cursor_position    ; Set up cursor position
  1309.     int Screen        ; Do it
  1310.  
  1311. ; We just updated the visible screen, now update the invisible one ...
  1312. ;   ... this is very slow (which is why we updated the visible screen first).
  1313.  
  1314.     or Screen_flags, Force_screen_update ; Do a whole lot of work
  1315.     jmp Do_our_screen    ; Use standard routine to install it,
  1316.                 ;  return from there
  1317.  
  1318. ReInit_Screen ENDP
  1319.  
  1320.  
  1321. ; Save and restore command mode screen
  1322.  
  1323.     PUBLIC Save_command_mode_screen
  1324.  
  1325. Save_command_mode_screen PROC
  1326.  
  1327.     call Beam_Off        ; Suppress video during copy of screen
  1328.     sub si, si        ; Start at zero
  1329.     mov di, OFFSET Command_mode_screen ; Destination OFFSET within segment
  1330.     mov cx, Number_of_chars_on_PC_screen ; Full PC screen
  1331.     push ds            ; Save ds
  1332.     call Get_Screen_Segment ; Get address of our ds
  1333.     mov ds, ax        ; Install it
  1334.     mov ax, Alloc_ds    ; Pick up ptr to allocated segment
  1335.     mov es, ax        ; Set up in es -- Command_mode_screen's seg
  1336.     ASSUME es:Alloc
  1337.     cld            ; Forwards
  1338.     rep movsw        ; Blast out the screen
  1339.     pop ds            ; Get back ds
  1340.     mov ah, 3        ; Code to read cursor position
  1341.     sub bh, bh        ; Page zero
  1342.     int Screen        ; Get cursor position
  1343.     mov Command_mode_cursor, dx ; Save for later
  1344.     mov ax, Datas_ds    ; Pick up normal ds
  1345.     mov es, ax        ; Reinstall in es
  1346.     ASSUME es:DataS
  1347.     jmp Beam_On        ; Re-enable video
  1348.  
  1349. Save_command_mode_screen ENDP
  1350.  
  1351. Restore_command_mode_screen PROC
  1352.  
  1353.     call Go_to_page_zero    ; Be on page zero in display memory
  1354.     call Beam_Off        ; Suppress video during copy of screen
  1355.     mov si, OFFSET Command_mode_screen ; Source OFFSET within segment
  1356.     sub di, di        ; Start at zero
  1357.     mov cx, Number_of_chars_on_PC_screen ; Full PC screen
  1358.     push es            ; Save reg
  1359.     call Get_Screen_Segment ; Get address of our screen
  1360.     mov es, ax        ; Install it
  1361.     mov ax, Alloc_ds    ; Pick up ptr to allocated segment
  1362.     mov ds, ax        ; Set up in ds -- Command_mode_screen's seg
  1363.     ASSUME ds:Alloc
  1364.     cld            ; Forwards
  1365.     rep movsw        ; Blast out the screen
  1366.     pop es            ; Get back reg
  1367.     mov ah, 2        ; Code to set cursor position
  1368.     sub bh, bh        ; Page zero
  1369.     mov dx, Command_mode_cursor ; Get back saved cursor position
  1370.     int Screen        ; Set cursor position
  1371.     mov ax, Datas_ds    ; Pick up normal ds
  1372.     mov ds, ax        ; Reinstall in es
  1373.     ASSUME ds:DataS
  1374.     jmp Beam_On        ; Re-enable video
  1375.  
  1376. Restore_command_mode_screen ENDP
  1377.  
  1378.  
  1379. ; Assemble mode line, then install in screen buffer
  1380.  
  1381.     PUBLIC Do_mode_line
  1382.  
  1383. Do_mode_line PROC
  1384.  
  1385.     test flags, modoff    ; Is the mode line disabled?
  1386.      jz DML_Do_it        ;  No, go draw it
  1387.  
  1388.     jmp Erase_mode_line    ; Blow away old mode line, ret from there
  1389.  
  1390. DML_Do_it:
  1391.     mov ah, 2        ; Code to get shift states
  1392.     int Kb            ; Get them
  1393.  
  1394.     mov dx, ax        ; Save state for later
  1395.  
  1396.     mov al, Esc_ch        ; Get the escape character
  1397.     cmp al, Space        ; Is it a control char?
  1398.      jge DML_No_carat    ;  No, don't type the carat
  1399.  
  1400.     mov M_Esc,'^'        ; Store a carat
  1401.     add al, 40h        ; Convert char to printable version
  1402.     mov M_Esc + 1, al    ; Store the fixed-up char
  1403.     jmp SHORT DML_Print    ; Skip code for no carat
  1404.  
  1405. DML_No_carat:
  1406.     mov M_Esc, al        ; Store the char
  1407.     mov M_Esc + 1, Space    ; Space following
  1408.  
  1409. DML_Print:
  1410.     mov si, OFFSET M_Prt_Off ; Assume printing is off
  1411.  
  1412.     test VT100_status_flags, Printer_wanted ; In one of these modes?
  1413.      jnz DML_Print_on    ;  Yes, say Prt is on
  1414.  
  1415.     test flags1, prtscr    ; Should we be printing?
  1416.      jz DML_Write_Prt    ;  No
  1417.  
  1418. DML_Print_on:
  1419.     mov si, OFFSET M_Prt_On ; Printing is on
  1420.  
  1421. DML_Write_Prt:
  1422.     mov di, OFFSET M_Prt    ; Where to write the data
  1423.     mov cx, M_Prt_length    ; The number of chars to copy
  1424.     cld            ; Forwards
  1425.     rep movsb        ; Copy the bytes into the mode line
  1426.  
  1427.     mov di, OFFSET M_Caps    ; Put data here
  1428.     mov si, OFFSET Caps    ; String to say CAPS
  1429.     mov cx, 4        ; Number of bytes
  1430.     test dl, Caps_State    ; Is it set?
  1431.      jnz DML_KPad        ;  We are in CAPS state, go say so
  1432.  
  1433.     mov si, OFFSET Lc    ; Not in CAPS state
  1434. DML_KPad:
  1435.     rep movsb        ; Copy the bytes
  1436.  
  1437.     mov di, OFFSET M_KPad    ; Put data here
  1438.     mov si, OFFSET Num    ; String to say NumL
  1439.     mov cx, 4        ; Number of bytes
  1440.     test dl, Num_State    ; Is it set?
  1441.      jnz DML_LED        ;  We are in Num state, go say so
  1442.  
  1443.     mov si, OFFSET Arrow    ; Not in Num state
  1444. DML_LED:
  1445.     rep movsb        ; Copy the bytes
  1446.  
  1447.     mov al, 70h        ; Normal
  1448.     test LEDs, LED1        ; Is this LED lit?
  1449.      jz DML_L1        ;  No
  1450.  
  1451.     mov al, 0f0h        ; 
  1452. DML_L1:    mov M_L1, al        ; Set attr for this LED
  1453.  
  1454.     mov al, 70h        ; Normal
  1455.     test LEDs, LED2        ; Is this LED lit?
  1456.      jz DML_L2        ;  No
  1457.  
  1458.     mov al, 0f0h        ; 
  1459. DML_L2:    mov M_L2, al        ; Set attr for this LED
  1460.  
  1461.     mov al, 70h        ; Normal
  1462.     test LEDs, LED3        ; Is this LED lit?
  1463.      jz DML_L3        ;  No
  1464.  
  1465.     mov al, 0f0h        ; 
  1466. DML_L3:    mov M_L3, al        ; Set attr for this LED
  1467.  
  1468.     mov al, 70h        ; Normal
  1469.     test LEDs, LED4        ; Is this LED lit?
  1470.      jz DML_L4        ;  No
  1471.  
  1472.     mov al, 0f0h
  1473. DML_L4:    mov M_L4, al        ; Set attr for this LED
  1474.  
  1475.     mov si, OFFSET Mode_template ; Start at beginning
  1476.  
  1477. ; Fall through to ...
  1478.  
  1479. ; Build mode line -- Use assembled template to generate the mode line
  1480.  
  1481. ;  Call with
  1482. ;    si/ ptr to template to use
  1483.  
  1484. Build_mode_line:
  1485.     call Erase_mode_line    ; Erase any existing mode line
  1486.     mov di, OFFSET Mode_line ; Store the mode line here
  1487.  
  1488.     mov ax, Alloc_ds    ; Ptr to Allocated data segment
  1489.     mov es, ax        ; Set up es
  1490.     ASSUME es:Alloc
  1491.  
  1492. Next_Attr:
  1493.     lodsb            ; Pick up attribute
  1494.     or al, al        ; End-of-the-line?
  1495.      je BML_End        ;  Done building mode line
  1496.  
  1497.     cmp Force_mono, 0    ; Are we stuck with mono no matter what?
  1498.      jne Do_mono        ;  Yes
  1499.  
  1500.     cmp CRT_Mode, 7        ; Monochrome card?
  1501.      jne Use_attr        ;  Color, use what we have set up
  1502.  
  1503. ; Monochrome card does rude things to attributes that look nice in color
  1504. ;  Use different attributes
  1505.  
  1506. Do_mono:
  1507.     cmp al, 71h        ; Highlighted?
  1508.      jne Use_attr        ;  No
  1509.  
  1510.     mov al, 70h        ; Be a square, leave it just inverted
  1511.  
  1512. Use_attr:
  1513.     mov bl, al        ; Save attr in bl
  1514.  
  1515. Next_Char:
  1516.     lodsb            ; Get the next char
  1517.     or al, al        ; Done with this attr?
  1518.      je Next_Attr        ;  Yes, go try for another
  1519.  
  1520.     stosb            ; Store the byte in the mode line
  1521.     mov al, bl        ; Get the current attr
  1522.     stosb            ; Store it too
  1523.     jmp Next_Char        ; Go do another char
  1524.  
  1525. BML_End:
  1526.     mov ax, Datas        ; Ptr to normal data segment
  1527.     mov es, ax        ; Restore es
  1528.     ASSUME es:Datas
  1529.  
  1530.     ret
  1531.  
  1532. Do_mode_line ENDP
  1533.  
  1534.  
  1535. ; Set internal mode line to normal video spaces
  1536.  
  1537. Erase_mode_line    PROC
  1538.  
  1539.     mov di, OFFSET Mode_line ; Ptr to mode line
  1540.     mov cx, Number_of_columns ; Number of words in the line
  1541.  
  1542.     mov ax, Alloc_ds    ; Ptr to allocated ds
  1543.     mov es, ax        ; Install in es
  1544.     ASSUME es:Alloc
  1545.  
  1546.     mov ax, 0720h        ; Normal blanks
  1547.     cld            ; Moving forwards
  1548.     rep stosw        ; Store this in the whole line
  1549.  
  1550.     mov ax, Datas_ds    ; Ptr to normal ds
  1551.     mov es, ax        ; Install in es
  1552.     ASSUME es:Datas
  1553.  
  1554.     or Screen_flags, Screen_changed ; Flag screen change
  1555.     ret            ; Done here
  1556.  
  1557. Erase_mode_line    ENDP
  1558.  
  1559.  
  1560. ; Routine to get as many chars from port as possible, 
  1561. ;  and update screen accordingly
  1562.  
  1563.     PUBLIC Do_screen
  1564.  
  1565. Do_Screen PROC
  1566.  
  1567.     cmp Count, 0        ; Are there any chars we haven't seen already?
  1568.      jne DOS_1        ;  Yes, deal with them
  1569.  
  1570.     jmp No_more_chars    ; No chars, don't waste time here
  1571.  
  1572. DOS_1:    sub ax, ax        ; Get a zero
  1573.     mov Previous_char, al    ; No last character
  1574.     mov Backed_up_char, al    ; No backed-up character
  1575.     mov Number_of_chars_done, ax ; Haven't done any chars yet
  1576.     mov Number_of_scrolls_done, ax ; These either
  1577.  
  1578.     mov ax, OFFSET EBuffr    ; Get pointer to beginning of esc buffer
  1579.     mov EBufGt, ax        ; Save as new getter ptr so we will pick
  1580.                 ;  up any sequence already partially read
  1581.  
  1582.     mov Save_SP_for_abort, sp ; Save a copy of the current stack ptr
  1583.                 ;  in case we have to blow out an escape seq
  1584.                 ;  in the middle ...
  1585.  
  1586.     PUBLIC Get_next_char
  1587.  
  1588. Get_next_char:
  1589.  
  1590.     cmp Allow_blast, 0    ; Flag set?
  1591.      jnz Got_1        ;  Yes, skip this test
  1592.  
  1593.     mov ax, Number_of_chars_done ; Number done so far
  1594.     cmp ax, Max_number_of_chars ; Too many?
  1595.      jl Got_1        ;  Not yet
  1596.  
  1597.     jmp No_more_chars    ; Did all we`re allowed, pretend no more
  1598.  
  1599. Got_1:    inc ax            ; Bump by one
  1600.     mov Number_of_chars_done, ax ; Store updated count
  1601.  
  1602.     mov al, VT100_status_flags ; Get current status flags
  1603.     mov Old_status_flags, al ; Save for later
  1604.  
  1605.     Call PullCh        ; Get a char from somewhere
  1606.      jmp No_more_chars    ;  No char to get, done here
  1607.  
  1608.     cmp al, Esc        ; Is it an escape?
  1609.      jne GNC_1        ;  No
  1610.  
  1611.     mov Hit_ESC, 0FFh    ; Flag that we hit an escape
  1612.     jmp Do_Escape        ; Go handle it
  1613.  
  1614. GNC_1:    mov Hit_ESC, 0        ; Not in an esc seq
  1615.     test VT100_status_flags, Printer_controller_mode ; In funny mode?
  1616.      jz GNC_2        ;  No, deal with it as usual
  1617.  
  1618.     jmp SHORT Done_with_char ; In this mode we mostly ignore chars
  1619.  
  1620. GNC_2:    cmp al, Space        ; Compare with space ...
  1621.      jge Do_Add        ;  If space or greater, just add it
  1622.  
  1623.     mov bx, OFFSET ActTb1    ; Action table
  1624.     mov cx, NChrTb1        ; Number of chars to check
  1625.     mov dx, OFFSET ChrTb1    ; Character table to use
  1626.     jmp SHORT Check_Table    ; Do the lookup and dispatch
  1627.  
  1628.  
  1629. ; Add this char to the stored line
  1630.  
  1631. Do_Add:    call Add_this_char    ; Add this char, fall thru to ...
  1632.  
  1633.  
  1634. ; Done_with_char  ==  Bottom of loop:
  1635. ;
  1636. ;  If we were if "Printer Controller Mode" when we started this and we
  1637. ;    are still in it now, then now is the time to dump the sequence to
  1638. ;    the printer.
  1639. ;  This lets all intended ESC sequences make it to the printer, but
  1640. ;    suppresses both the $[5i that puts us into Printer Controller Mode
  1641. ;    (because we were not in the Mode to start) and the $[4i that makes
  1642. ;    us leave the mode (because we are not in the mode now).
  1643. ;
  1644. ;  Close out any active Esc sequence.
  1645. ;
  1646. ;  Go see if there are any more characters to be read.
  1647.  
  1648.     PUBLIC Done_with_char
  1649.  
  1650. Done_with_char:
  1651.  
  1652.     mov ax, OFFSET EBuffr    ; Get pointer to beginning of esc buffer
  1653.     mov EBufGt, ax        ; Save as new getter ptr so we will pick
  1654.                 ;  up any sequence that we have just read
  1655.  
  1656.     test flags1, prtscr    ; Should we be printing?
  1657.      jnz DWC_Print        ;  Yes
  1658.  
  1659. ; Printer_wanted = Printer_controller_mode + Auto_copy_mode
  1660.  
  1661.     test VT100_status_flags, Printer_wanted ; In a print mode?
  1662.      jz DWC_0        ;  No
  1663.  
  1664.     test Old_status_flags, Printer_wanted ; Were we before?
  1665.      jz DWC_0        ;  No
  1666.  
  1667. DWC_Print:
  1668.     mov bx, EBufGt        ; Escape buf getter ptr
  1669.     cmp bx, EBufPt        ; Compare with putter ptr
  1670.      je DWC_0        ;  If same, no chars held there
  1671.  
  1672.     mov dl, [bx]        ; Pick up the char
  1673.     inc EBufGt        ; Bump the ptr
  1674.     mov ah, LstOut        ; Code to print a character
  1675.     int DOS            ; Print this character
  1676.  
  1677.     jmp DWC_Print        ; See if any more to do
  1678.  
  1679.  
  1680. DWC_0:    sub al, al        ; Make a zero
  1681.     mov Backed_up_char, al    ; Clobber "backed-up" char
  1682.     call Flush_esc_buffer    ; Trash escae buffer
  1683.  
  1684.     cmp Quit_emulator, 0    ; Are we quitting?
  1685.      jne No_more_chars    ;  Yes
  1686.  
  1687.     cmp Allow_blast, 0    ; Flag set?
  1688.      jnz DWC_1        ;  Yes, skip slowdown test
  1689.  
  1690.     mov ax, Number_of_scrolls_done
  1691.     cmp ax, Maximum_scrolls    ; Scrolled enough to have to stop and update?
  1692.      jge No_more_chars    ;  Yes
  1693.  
  1694. DWC_1:    jmp Get_next_char    ; Do more
  1695.  
  1696. ; Abort processing, possibly in the middle of decoding an esc seq
  1697.  
  1698. Abort_esc_sequence:
  1699.  
  1700.     mov sp, Save_SP_for_abort ; Get back saved stack pointer
  1701.     jmp Done_with_char    ; Go clean it up
  1702.  
  1703.  
  1704. ; Leaving screen update state, install buffer in screen memory if required
  1705.  
  1706.     PUBLIC No_more_chars
  1707.  
  1708. No_more_chars:
  1709.  
  1710.     mov ah, 2        ; Code to get shift state
  1711.     int KB            ; Get it
  1712.  
  1713.     and al, Num_state + Caps_state ; Check only these
  1714.     cmp al, Prev_shift_state ; Did something change?
  1715.      je End_of_pass        ;  No
  1716.  
  1717.     mov Prev_shift_state, al ; Save for next time
  1718.     call Do_mode_line    ; Go make a new mode line
  1719.  
  1720. End_of_pass:
  1721.  
  1722.     test Screen_flags, Changed ; Did something change?
  1723.      jz EOP_1        ;  No
  1724.  
  1725.     jmp Do_our_screen    ; Use standard routine to install it,
  1726.                 ;  return from there
  1727.  
  1728. EOP_1:    ret            ; Done here
  1729.  
  1730. Do_Screen ENDP
  1731.  
  1732.  
  1733. ; Routine to search a table of chars for a desired char, then
  1734. ;  dispatch to another routine based on where the string was found, 
  1735. ;  or if it was not found
  1736. ;
  1737. ;  Call with ...
  1738. ;    al/ char to search for
  1739. ;    bx/ table of jump addresses (each entry one word) ... number of
  1740. ;        entries is one greater than number of entries in search
  1741. ;        table -- final entry is used if the search fails
  1742. ;    cx/ number of bytes in search table
  1743. ;    dx/ table to search in (each entry one byte)
  1744. ; Trashes most of these, also di ...
  1745.  
  1746. Check_Table PROC
  1747.  
  1748.     mov di, dx        ; Copy over addr of table
  1749.     cld            ; Forwards
  1750.     repne scasb        ; Search for char in table
  1751.      jne Chk_1        ;  If search failed, don't back up ptr
  1752.  
  1753.     dec di            ; Drop by one due to REPNE overshoot
  1754.  
  1755. Chk_1:    sub di, dx        ; Get index of char
  1756.     shl di, 1        ; Double for word offset
  1757.     add bx, di        ; Add displacement to base of action table
  1758.     jmp WORD PTR [bx]    ; Dispatch to the desired routine
  1759.  
  1760. Check_Table ENDP
  1761.  
  1762.  
  1763. ; Routine to flush the Escape buffer
  1764.  
  1765. Flush_esc_buffer PROC
  1766.  
  1767.     mov ax, OFFSET EBuffr    ; Address of Escape buffer
  1768.     mov EBufGt, ax        ; Set up as getter ptr
  1769.     mov EBufPt, ax        ; Set up as putter ptr also
  1770.     mov EBufCt, 0        ; Clear ebuf count
  1771.     mov Hit_ESC, 0        ; Not in an esc seq now
  1772.     ret            ; Done here
  1773.  
  1774. Flush_esc_buffer ENDP
  1775.  
  1776.  
  1777. ;******************************************************************************
  1778.  
  1779. ; *General utilities ...
  1780.  
  1781. ; Get shift state into al.  We only care about shift, ctl, and alt keys.
  1782. ;  Right shift is collapsed into left shift.
  1783.  
  1784. Gss    PROC
  1785.  
  1786.     mov ah, 2
  1787.     int Kb            ; get current shift state
  1788.  
  1789.     mov bl, al        ; copy for a moment
  1790.     and bl, right_shift    ; mask out all but right shift
  1791.     shl bl, 1        ; move right shift to left shift pos
  1792.     or al, bl        ; collapse shift bits
  1793.     and al, (left_shift + alt_shift + ctl_shift)
  1794.     ret
  1795.  
  1796. Gss    ENDP
  1797.  
  1798.  
  1799. ; Send_char_to_port -- Send the character in al out to the serial port
  1800.  
  1801. ; Call with
  1802. ;    al/ char to be sent
  1803.  
  1804. Send_char_to_port PROC
  1805.  
  1806.     test flags, lclecho    ; Local echo on?
  1807.      jz SCP_Noecho        ;  No
  1808.  
  1809.     call Type_to_screen    ; Echo every character immediately
  1810.  
  1811. SCP_Noecho:
  1812.     mov ah, al        ; this is where outchr expects it
  1813.     call OutChr_PC        ; output to the port
  1814.      RetNop
  1815.  
  1816.     ret
  1817.  
  1818. Send_char_to_port ENDP
  1819.  
  1820.  
  1821. ; Returns with carry on if a character is available
  1822.  
  1823.     PUBLIC Get_char_from_port
  1824.  
  1825. Get_char_from_port PROC
  1826.  
  1827.     push dx            ; PrtChr_PC clobbers dx
  1828.     call PrtChr_PC        ; Character at port?
  1829.      jmp SHORT portc1    ;  Yes, go handle
  1830.      nop            ;  3 bytes
  1831.  
  1832.     clc            ; No carry -> no character
  1833.     jmp SHORT portc2    ; Go finish up
  1834.  
  1835. portc1:    and al, 7Fh        ; We don't worry about parity here
  1836.     stc            ; Have a character
  1837.  
  1838. portc2:    pop dx            ; Get back saved reg
  1839.     ret            ;  and return
  1840.  
  1841. Get_char_from_port ENDP
  1842.  
  1843.  
  1844.     PUBLIC Handle_keystroke
  1845.  
  1846. Handle_keystroke PROC
  1847.  
  1848.     push ax            ; Save original value
  1849.  
  1850.     mov al, ah        ; put scan code into al
  1851.     mov ah, bl        ; shift state into ah
  1852.  
  1853.     cmp ax, (256*ctl_shift) ; Is this control-break?
  1854.      jne Not_Break        ;  No
  1855.  
  1856.     pop ax            ; Fix stack
  1857.  
  1858.     mov ah, DConIo
  1859.     mov dl, 0FFh
  1860.     int Dos            ; Read the bogus ^C DOS gets
  1861.  
  1862.     jmp SendBr        ; Use other routine to send the break
  1863.  
  1864. Not_Break:
  1865.     cmp ax, (ctl_shift*256)+CtrlPrtSc
  1866.      jne Not_PrtSc
  1867.  
  1868.     call trnprs        ; Toggle the print screen setting
  1869.     pop ax
  1870.     ret
  1871.  
  1872. Not_PrtSc:
  1873.     cmp ax, (ctl_shift*256)+57 ; Control-space?
  1874.      jne Not_Ctrl_Space    ;  No
  1875.  
  1876.     sub al, al        ; Want a null
  1877.     call Send_char_to_port    ; Send it out
  1878.     pop ax            ; Get back saved reg
  1879.     ret            ; Done here
  1880.  
  1881. Not_Ctrl_Space:
  1882.     cmp ax, (alt_shift*256)+108 ; Alt F5?
  1883.      jne Not_ALT5        ;  No
  1884.  
  1885.     pop ax
  1886.     jmp Leave_emulator    ; Want to get out
  1887.  
  1888. Not_ALT5:
  1889.     cmp ax, (alt_shift*256)+109 ; ALT F6?
  1890.      jne Not_ALT6        ;  No
  1891.  
  1892.     pop ax
  1893.     jmp Call_Helper        ; Call the help module
  1894.  
  1895. Not_ALT6:
  1896.     cmp ax, (alt_shift*256)+110 ; ALT F7?
  1897.      jne Not_ALT7        ;  No
  1898.  
  1899.     pop ax
  1900.     jmp Leave_program    ; Want to get all the way out
  1901.  
  1902. Not_ALT7:
  1903.     cmp ax, (alt_shift*256)+111 ; ALT F8?
  1904.      jne Not_ALT8        ;  No
  1905.  
  1906.     pop ax
  1907.     call Go_to_page_zero    ; Go to base page
  1908.     mov dx, (256*24) + 0    ; Lower left corner of screen
  1909.     call PosCur_PC        ; Go there
  1910.     call ClrMod_PC        ; Erase mode line (it's in inverse video)
  1911.     call Quick_Push        ; Push directly from here
  1912.      nop            ;  Skips on success
  1913.      nop
  1914.      nop
  1915.     call SerIni_PC        ; In case it got turned off ...
  1916.     or Screen_flags, Force_screen_update ; Update the world
  1917.     jmp Do_our_screen    ; Restore our screen, ret from there
  1918.  
  1919. Not_ALT8:
  1920.     cmp m7171, 0        ; In 7171 mode?
  1921.      jz Not_7171        ;  No
  1922.  
  1923.     mov cx, Number_of_key_codes_7171 ; Number of entries to check
  1924.     mov dx, OFFSET Key_codes_7171 ; Scan code table to use
  1925.     mov di, dx        ; Copy over addr of table
  1926.     cld            ; Forwards
  1927.     repne scasw        ; Search for word in table
  1928.      jne HAN_1        ;  Search failed, go do something else
  1929.  
  1930.     mov bx, OFFSET Key_actions_7171 ; Action table for 7171 mode
  1931.     mov cx, di        ; Copy to cx
  1932.     dec cx            ; Drop by one word due to REPNE overshoot
  1933.     dec cx            ;  ...
  1934.     sub cx, dx        ; Get index of char
  1935.     add bx, cx        ; Add displacement to base of action table
  1936.     mov si, [bx]        ; Pick up addr of string to send
  1937.     call Send_str_to_port    ; Send it out
  1938.     pop ax            ; Get back reg
  1939.     ret            ; Done here
  1940.  
  1941.  
  1942.  %OUT >> About half way through source file
  1943.  
  1944.  
  1945. Not_7171:
  1946.     mov cx, Number_of_key_codes ; Number of entries to check
  1947.     mov dx, OFFSET Key_codes ; Scan code table to use
  1948.     mov di, dx        ; Copy over addr of table
  1949.     cld            ; Forwards
  1950.     repne scasw        ; Search for word in table
  1951.      jne HAN_1        ;  Search failed, go do something else
  1952.  
  1953.     mov bx, OFFSET Key_actions ; Action table
  1954.     mov cx, di        ; Copy to cx
  1955.     dec cx            ; Drop by one word due to REPNE overshoot
  1956.     dec cx            ;  ...
  1957.     sub cx, dx        ; Get index of char
  1958.     add bx, cx        ; Add displacement to base of action table
  1959.     add bx, cx        ; Double the offset
  1960.     add bx, cx        ; Triple it (6 bytes instead of 2)
  1961.     lea dx, 2[bx]        ; Get 2 + <addr of <addr of routine>> into dx
  1962.     call WORD PTR [bx]    ; Dispatch to the desired routine, but come
  1963.                 ;  back when done ...
  1964.  
  1965.     pop ax            ; Get back reg
  1966.     ret            ; Done here
  1967.  
  1968.  
  1969. ; Translate the scan code in ah according to the translate table
  1970. ;  given in ktrntab/krpltab, output to port.  If no translation, 
  1971. ;  use ascii char in al.
  1972.  
  1973. HAN_1:    test flags, havtt    ; translate table given?
  1974.      jnz HAN_2        ;  Yes, check it out
  1975.  
  1976.     pop ax            ; Get back reg
  1977.     jmp SHORT HAN_3        ; Go output it normally
  1978.  
  1979. HAN_2:    mov di, ktrntab        ; pick up translate tbl
  1980.     mov cx, ktlen        ; length of tbl
  1981.     cld            ; Forwards
  1982.     repne scasw        ; look for our key
  1983.  
  1984.     pop ax            ; recover character
  1985.      jne HAN_3        ; not found, forget it
  1986.  
  1987.     sub di, ktrntab        ; get index into tbl
  1988.     sub di, 2        ; (minus 2 for pre-increment)
  1989.     mov bx, krpltab        ; get replacement table
  1990.     mov si, [bx][di]    ; and addr of replacement
  1991.     mov al, [si]        ; Get first byte (length)
  1992.     cbw            ; Blow up
  1993.     mov bx, ax        ; Copy to bx
  1994.     inc si            ; Point to translation string
  1995.     sub al, al        ; Get a zero
  1996.     mov [si][bx], al    ; Tie off the string at its declared length
  1997.     jmp Send_str_to_port    ; Send it off to the port
  1998.  
  1999. HAN_3:    call Send_char_to_port    ; just output single char
  2000.     ret            ; and return
  2001.  
  2002. trnprs:    xor Flags1, PrtScr    ; Flip the flag
  2003.     mov Prev_shift_state, 0FFh ; Store an impossible setting to force
  2004.                 ;   a redraw of mode line
  2005.     ret
  2006.  
  2007. Handle_keystroke ENDP
  2008.  
  2009.  
  2010. ; puts current screen segment in ax
  2011.  
  2012. Get_screen_segment PROC
  2013.  
  2014.     mov ax, 0b000h        ; assume bw for now
  2015.     cmp CRT_Mode, 7        ; 7 is bw (***)
  2016.      je scrse1
  2017.  
  2018.     mov ax, 0b800h        ; color card
  2019.  
  2020. scrse1:    ret
  2021.  
  2022. Get_screen_segment ENDP
  2023.  
  2024.  
  2025. ; Do_our_screen -- Internal routine to set up for and call Put_Screen
  2026.  
  2027. Do_our_screen PROC
  2028.  
  2029.     mov ax, Alloc_ds    ; Pick up ptr to allocated ds
  2030.     mov es, ax        ; Install in es
  2031.     ASSUME es:Alloc
  2032.     mov ax, Cursor_position    ; Pick up cursor pos from DATAS segment
  2033.     mov Alloc_cursor_position, ax ; Install it in the Alloc segment
  2034.  
  2035.     mov bx, OFFSET Screen_image ; Ptr to our internal screen image
  2036.     call Put_Screen
  2037.  
  2038.     mov ax, Datas_ds    ; Restore normal pointer ...
  2039.     mov es, ax        ;  to es
  2040.     ASSUME es:Datas
  2041.     ret            ; DOne here
  2042.  
  2043. Do_our_screen ENDP
  2044.  
  2045.  
  2046. ; Put_Screen -- Copy a new screen image and mode line into display memory
  2047.  
  2048. ; call with
  2049. ;    es:bx/ ptr to image to put on the screen, compared to old image
  2050.  
  2051.     PUBLIC Put_Screen
  2052.  
  2053. Put_Screen PROC
  2054.  
  2055.     ASSUME es:Nothing
  2056.     mov Image_ptr, bx    ; Save parameter
  2057.     sub bx, 2        ; Back up to Cursor pos
  2058.     mov ax, es:[bx]        ; Pick it up
  2059.     mov Cursor, ax        ; Store in local variable
  2060.  
  2061.     cld            ; Forwards
  2062.  
  2063.     test Screen_flags, Screen_changed + Line_changed + Force_screen_update
  2064.      jz PSC_Position    ;  If only position changed, update only it
  2065.  
  2066.     cmp cs:Which_card, 1    ; Color card?
  2067.      je PSC_Color        ;  Yes, go do strange update
  2068.  
  2069.     mov si, Image_ptr    ; Source for transfer
  2070.     push ds            ; Save ds
  2071.     push es            ; Save es
  2072.     mov ax, es        ; Copy es
  2073.     mov ds, ax        ;  to ds
  2074.     mov ax, 0B000h        ; Address of mono card memory
  2075.  
  2076.     cmp cs:Which_card, 2    ; Is this really the EGA in color mode?
  2077.      jne Not_EGA        ;  No
  2078.  
  2079.     mov ax, 0B800h        ; EGA in color mode, use color address
  2080.  
  2081. Not_EGA:
  2082.     mov es, ax        ; Install in es reg
  2083.     sub di, di        ; Destination OFFSET within segment
  2084.     mov cx, Number_of_chars_on_PC_screen ; Full screen
  2085.     rep movsw        ; Blast out the screen
  2086.     pop es            ; Get back original es
  2087.     pop ds            ;  and ds
  2088.  
  2089.     jmp SHORT PSC_Position    ; Go set position and finish up
  2090.  
  2091.     PUBLIC PSC_Color
  2092.  
  2093. PSC_Color:
  2094.     call Build_update_list    ; First build an update list of locations
  2095.                 ;  to be changed, updating Old_Image as we go
  2096.  
  2097.     mov ax, Number_of_update_items ; See how many there are to do
  2098.     or ax, ax        ; Are there any?
  2099.      jnz PSC_Update        ;  Yes, go do them
  2100.  
  2101. PSC_Position:
  2102.     mov dx, Cursor        ; Get current cursor pos
  2103.     mov ah, 2        ; Code to set cursor position
  2104.     mov bh, Which_page    ; The current page
  2105.     int Screen        ; Set cursor position
  2106.  
  2107.     jmp SHORT PSC_Done    ; Go finish up
  2108.  
  2109. PSC_Update:
  2110.     call Update_nondisplayed_page ; Run the update list against the
  2111.                 ;  page the user can't see
  2112.  
  2113.     mov dx, Cursor        ; Get current cursor pos
  2114.     mov ah, 2        ; Code to set cursor position
  2115.     mov bh, 1        ; Get a 1
  2116.     sub bh, Which_page    ; Minus current page number = other page
  2117.     int Screen        ; Set cursor position
  2118.  
  2119.     call Switch_video_pages    ; Then switch pages ...
  2120.  
  2121.     call Update_nondisplayed_page ; Then run the update list against the
  2122.                 ;  page we were just on
  2123.     mov dx, Cursor        ; Get current cursor pos
  2124.     mov ah, 2        ; Code to set cursor position
  2125.     mov bh, 1        ; Get a 1
  2126.     sub bh, Which_page    ; Minus current page number = other page
  2127.     int Screen        ; Set cursor position
  2128.  
  2129.     call Switch_video_pages    ; Then switch pages ...
  2130.  
  2131. PSC_Done:
  2132.     and Screen_flags, NOT ( Changed + Force_screen_update )
  2133.                 ; Screen + position are all set
  2134.  
  2135.     ret            ; Go home
  2136.  
  2137.     PUBLIC Build_update_list
  2138.  
  2139. Build_update_list:
  2140.     mov si, OFFSET Old_Image ; Ptr to old image
  2141.     mov di, Image_ptr    ; Ptr to new image
  2142.     mov cx, Number_of_chars_on_PC_screen ; The number of words to compare
  2143.     sub bx, bx        ; Clear count of update items
  2144.  
  2145.     test Screen_flags, Force_screen_update ; Want to do all locations?
  2146.  
  2147.     mov ax, Alloc_ds    ; Pick up ptr to allocated segment
  2148.     mov ds, ax        ; Make ds point to it
  2149.     ASSUME ds:Alloc
  2150.  
  2151.      jz BUL_Top        ;  No, go do it minimally
  2152.  
  2153. BUL_Zap:
  2154.     add si, 2        ; Bump the pointers
  2155.     add di, 2
  2156.     call BUL_Do_difference    ; Do the next character
  2157.  
  2158.     dec cx            ; Decr counter
  2159.      jcxz BUL_Bot        ; No more to do
  2160.  
  2161.     jmp BUL_Zap        ; Go update the next character
  2162.  
  2163. BUL_Top: repe cmpsw        ; Are the old and new words the same?
  2164.     je BUL_Bot        ; This batch was all equal, done here
  2165.  
  2166.     call BUL_Do_difference    ; Deal with the difference
  2167.  
  2168.      jcxz BUL_Bot        ; If no more to do, stop now
  2169.  
  2170.     jmp BUL_Top        ; Go check the next pair of locations
  2171.  
  2172. ; Hit a difference, deal with it
  2173.  
  2174. BUL_Do_difference:
  2175.     mov dx, si        ; Copy source offset to dx
  2176.     mov ax, 2 + OFFSET Old_Image ; Pick up addr of buffer plus 2
  2177.     sub dx, ax        ; Get distance from start of buffer
  2178.     mov Update_list[bx], dx    ; Store offset ptr in update list
  2179.     mov ax, es:-2[di]    ; Pick up the new display value
  2180.     mov Update_list + 2[bx], ax ; Store it in the update list
  2181.     mov -2[si], ax        ; Store it in the old image screen too
  2182.     add bx, 4        ; Move to next item
  2183.     ret            ; Done here
  2184.  
  2185. BUL_Bot:
  2186.     mov ax, Datas_ds    ; Pick up ptr to normal segment
  2187.     mov ds, ax        ; Make ds point to it
  2188.     ASSUME ds:Datas
  2189.  
  2190.     shr bx, 1        ; Convert bytes to items
  2191.     shr bx, 1        ;  (divide by four)
  2192.     mov Number_of_update_items, bx ; Store the updated count of items
  2193.     ret            ; Done here
  2194.  
  2195.  
  2196.     PUBLIC Update_nondisplayed_page
  2197.  
  2198. Update_nondisplayed_page:
  2199.     push es            ; Save es
  2200.     push WORD PTR Number_of_update_items ; Save count of items
  2201.     mov bl, 1        ; Get a one
  2202.     sub bl, Which_page    ; Get number of page we ARE NOT on
  2203.     sub bh, bh        ; Zero top half of word
  2204.     shl bx, 1        ; Double for word offset
  2205.     mov ax, Video_page_addresses[bx] ; Pick up address of screen memory
  2206.     mov es, ax        ; Set es to point to the screen buffer
  2207.     mov bx, OFFSET Update_list ; Get ptr to update list
  2208.     mov cx, Number_of_update_items ; Get count of items to update
  2209.     mov dx, CRT_status_port    ; Pick up status port number
  2210.  
  2211.     mov ax, Alloc_ds    ; Pick up ptr to allocated segment
  2212.     mov ds, ax        ; Install it in ds
  2213.     ASSUME ds:Alloc
  2214.  
  2215.     mov di, [bx]        ; Get next address to update
  2216.     mov bp, 2[bx]        ; Get value to store
  2217.  
  2218. UNP_1:    in al, dx        ; Get status
  2219.     shr al, 1        ; Shift lower order bit into carry flag
  2220.      jc UNP_1        ;  In retrace, wait until not retrace
  2221.  
  2222.     cli            ; Ints off for this next loop
  2223.  
  2224. UNP_2:    in al, dx        ; Get status
  2225.     shr al, 1        ; Shift lower order bit into carry flag
  2226.      jnc UNP_2        ;  Not in retrace, wait until we are
  2227.  
  2228. ; This update is for a single item, takes place during horizontal retrace
  2229.  
  2230.     xchg ax, bp        ; Get back the char we need, save CRT flags
  2231.     stosw            ; Store the new value
  2232.     sti            ; Ints back on now
  2233.     add bx, 4        ; Move on to next item in list
  2234.     mov di, [bx]        ; Get next address to update
  2235.  
  2236.     in al, dx        ; Get status again
  2237.     test al, Vertical_retrace ; Test vertical retrace bit
  2238.      jnz UNP_Setup        ; If in vertical retrace, take advantage of it
  2239.  
  2240.     mov bp, 2[bx]        ; Get value to store
  2241.     loop UNP_1        ; Go do the next
  2242.  
  2243.     jmp SHORT UNP_Done    ; Did them all, go finish up
  2244.  
  2245. UNP_Setup:
  2246.     mov ax, 2[bx]        ; Get value to store
  2247.     dec cx            ; Decr to account for char we just did
  2248.     mov Number_of_update_items, cx ; First store the current count
  2249.  
  2250.     cmp cx, Max_number_of_items ; Too many?
  2251.      jle UNP_Ok        ;  No, this count is ok
  2252.  
  2253.     mov cx, Max_number_of_items ; Load up the maximum
  2254.  
  2255. UNP_Ok:    sub Number_of_update_items, cx ; Back off count by this many
  2256.  
  2257.     PUBLIC UNP_Inner
  2258.  
  2259. ; This update is for a group of items, takes place during vertical retrace
  2260.  
  2261. UNP_Inner:
  2262.     stosw            ; Store the new value
  2263.     add bx, 4        ; Move on to next item in list
  2264.     mov di, [bx]        ; Get next address to update
  2265.     mov ax, 2[bx]        ; Get value to store
  2266.     loop UNP_Inner        ; Go do the next
  2267.  
  2268.     mov bp, ax        ; Save the char for later
  2269.     mov cx, Number_of_update_items ; Get number of items remaining
  2270.     or cx, cx        ; Any left?
  2271.      jnz UNP_1        ;  Still some left, go do them
  2272.  
  2273. UNP_Done:
  2274.     mov ax, Datas_ds    ; Ptr to normal data segment
  2275.     mov ds, ax        ; Reinstall as ds
  2276.     ASSUME ds:Datas
  2277.  
  2278.     pop WORD PTR Number_of_update_items ; Get back count of item list
  2279.     pop es            ; Get back saved es
  2280.     ret            ; Done here
  2281.  
  2282.     ASSUME es:Datas
  2283.  
  2284. Put_Screen ENDP
  2285.  
  2286.  
  2287. ; Force all modes to be 80 by 25 text modes on IBM Color Graphics Adapter
  2288.  
  2289.     PUBLIC Enter_text_mode, Mode_Change_Table
  2290.  
  2291. Enter_text_mode:
  2292.     mov ah, 15        ; Code to get current video mode
  2293.     int Screen        ; Check it out
  2294.  
  2295.     cmp al, 10h        ; Too high?
  2296.      ja ETM_Mode_ok        ;  Yeah, ignore it
  2297.  
  2298.     mov dh, al        ; Save for a minute
  2299.     mov bx, OFFSET Mode_change_table ; Address of translation table
  2300.     xlat            ; Change modes
  2301.     cmp dh, al        ; Different?
  2302.      je ETM_Mode_ok        ;  Same thing, don't blink display
  2303.  
  2304.     push ax            ; Save reg
  2305.     call Blank_current_page    ; Clear out the graphic page
  2306.     pop ax            ; Restore reg
  2307.  
  2308.     mov ah, 0        ; Code to set mode
  2309.     int Screen        ; Set it up
  2310.  
  2311.     call Blank_current_page    ; Clear out the text page
  2312.  
  2313. ETM_Mode_ok:
  2314.     ret            ; Done here
  2315.  
  2316.     PUBLIC Set_pointers
  2317.  
  2318. Set_pointers PROC
  2319.  
  2320.     mov al, Row        ; Pick up current row number
  2321.     mov bl, 2*Number_of_columns ; Size of a line
  2322.     mul bl            ; Multiply it out
  2323.     add ax, OFFSET Screen_Image ; Add address of buffer
  2324.     mov Line_Ptr, ax    ; Store line pointer
  2325.  
  2326.     mov bl, Column        ; Pick up current column number
  2327.     sub bh, bh        ; Clear high order half of word
  2328.     shl bx, 1        ; Shift left by 1 to double
  2329.     add ax, bx        ; Add in the column offset
  2330.     mov Char_Ptr, ax    ; Store character pointer
  2331.  
  2332.     or Screen_flags, Position_changed ; Flag screen change
  2333.     ret            ; Done here
  2334.  
  2335. Set_pointers ENDP
  2336.  
  2337.  
  2338. ; Reset_esc_seq_reading -- Used to reset reading of Escape sequence
  2339.  
  2340. Reset_esc_seq_reading PROC
  2341.  
  2342.     call Flush_esc_buffer    ; First erase old escape buffer
  2343.     mov al, Esc        ; Get an escape
  2344.     jmp Store_char_in_esc_buffer ; Store it as the start of a new esc seq
  2345.  
  2346. Reset_esc_seq_reading ENDP
  2347.  
  2348.  
  2349. ; Send_str_to_port -- Send a string to the port
  2350.  
  2351. ; call with
  2352. ;    si/ ptr to string to send, zero terminated (ASCIZ)
  2353.  
  2354. Send_str_to_port PROC
  2355.  
  2356.     cld            ; Forwards
  2357.     lodsb            ; Get a char from the string
  2358.     or al, al        ; Equal to zero?
  2359.      je SSTP_1        ;  Yes, quit on a null
  2360.  
  2361.     push si            ; Save just in case
  2362.     call Send_char_to_port    ; Send this char to the port
  2363.     pop si            ; Get back saved ptr
  2364.  
  2365.     jmp Send_str_to_port    ; Go try for another char
  2366.  
  2367. SSTP_1:    ret            ; Hit null, done
  2368.  
  2369. Send_str_to_port ENDP
  2370.  
  2371.  
  2372. ; Send a different string depending on some flag
  2373.  
  2374. Send_depending PROC
  2375.  
  2376. If_cursor_keys_mode_set:
  2377.     test VT100_status_flags, Cursor_keys_mode ; See which way it is
  2378.      jz Leave_alone        ;  Normal, done here
  2379.  
  2380.     inc dx
  2381.     inc dx            ; Bump twice
  2382.     jmp SHORT Leave_alone    ; Go finish up
  2383.  
  2384.  
  2385. If_keypad_application_mode_set:
  2386.  
  2387. ; First, see if we are in NUM LOCK or ARROW KEY state ...
  2388.  
  2389.     push ax            ; Save ax
  2390.     mov ah, 2
  2391.     int Kb            ; Get current shift state
  2392.  
  2393.     mov bl, al        ; Copy to bl
  2394.     and bl, NUM_State    ; Mask out all but NUM_State
  2395.     mov cl, 4        ; This many
  2396.     shr bl, cl        ; Shift NUM_State into Shift state's position
  2397.     xor bl, al        ; Keep a 1 if states are different
  2398.     pop ax            ; Restore saved reg
  2399.  
  2400.     test bl, Left_Shift    ; Are we effectively in NUM_State?
  2401.      jnz IFK_NUM_State    ;  We are effectively in NUM_State, go do it
  2402.  
  2403. ; In arrow key state, either beep or dispatch an arrow key
  2404.  
  2405.     mov bx, OFFSET Key_actions_2 ; Action table
  2406.     mov cx, Number_of_key_codes_2 ; Number of entries to check
  2407.     mov dx, OFFSET Key_codes_2 ; Scan code table to use
  2408.     mov di, dx        ; Copy over addr of table
  2409.     cld            ; Forwards
  2410.     repne scasw        ; Search for word in table
  2411.  
  2412.     je IFK_Got_it        ; Keep going if we found the key
  2413.  
  2414.     jmp Boop        ; Else, just beep to say "meaningless key"
  2415.  
  2416. IFK_Got_it:
  2417.     mov cx, di        ; Copy to cx
  2418.     dec cx            ; Drop by one word due to REPNE overshoot
  2419.     dec cx            ;  ...
  2420.     sub cx, dx        ; Get index of char
  2421.     add bx, cx        ; Add displacement to base of action table
  2422.     add bx, cx        ; Double the offset
  2423.     add bx, cx        ; Triple it (6 bytes instead of 2)
  2424.     lea dx, 2[bx]        ; Get 2 + <addr of <addr of routine>> into dx
  2425.     jmp WORD PTR [bx]    ; Dispatch to the desired routine
  2426.  
  2427. IFK_NUM_State:
  2428.     test VT100_status_flags, Keypad_application_mode ; See which way it is
  2429.      jz Leave_alone        ;  Normal, done here
  2430.  
  2431.     inc dx
  2432.     inc dx            ; Bump twice
  2433.  
  2434. Leave_alone:
  2435.     mov bx, dx        ; Copy to bx
  2436.     mov si, [bx]        ; Pick up the proper pointer
  2437.     jmp Send_str_to_port    ; Ship the string out to the port
  2438.  
  2439. ; User hit ALT F7, first set flag for program exit, then ...
  2440.  
  2441. Leave_program:
  2442.     call Exit2        ; Set exit flag
  2443.      nop
  2444.      nop
  2445.      nop
  2446.  
  2447. ; User hit F5 or ALT F5, set flag to say we are leaving the emulator ...
  2448.  
  2449. Leave_emulator:
  2450.  
  2451.     mov Quit_emulator, 1    ; Set flag to 1
  2452.     ret            ; Done here
  2453.  
  2454. ; User hit F6, call the Helper module
  2455.  
  2456. Call_Helper:
  2457.  
  2458.     call Go_to_page_zero    ; Be on page zero in display memory
  2459.  
  2460.     mov dx, Cursor_position    ; Get current cursor pos
  2461.     mov ah, 2        ; Code to set cursor position
  2462.     mov bh, Which_page    ; The current page
  2463.     int Screen        ; Set cursor position
  2464.  
  2465.     call Helper        ; Call the help module
  2466.  
  2467.     or Screen_flags, Changed ; Mark that screen needs help
  2468.     call Do_our_screen    ; Update screen
  2469.  
  2470.     mov dx, Cursor_position    ; Get current cursor pos
  2471.     mov ah, 2        ; Code to set cursor position
  2472.     mov bh, Which_page    ; The current page
  2473.     int Screen        ; Set cursor position
  2474.  
  2475.     ret            ; Done here
  2476.  
  2477. Send_depending ENDP
  2478.  
  2479.  
  2480. ;***************************************************************************
  2481.  
  2482. ; *Utilities for decoding VT100 Esc sequences and acting on them
  2483.  
  2484. VT100_Utilities PROC
  2485.  
  2486. ; Stolen from BIOS ...
  2487.  
  2488. Beep:    mov al, 10110110b    ; timer initialization
  2489.     out timer + 3, al
  2490.     mov ax, beldiv        ; Bell divisor
  2491.     out timer + 2, al
  2492.     mov al, ah
  2493.     out timer + 2, al    ; output divisor
  2494.     in al, bel_prt
  2495.     mov ah, al        ; remember original value
  2496.     or al, 3        ; turn speaker on
  2497.     out bel_prt, al
  2498.     mov cx, 8888h
  2499. outbe1:    loop outbe1        ; wait a while
  2500.     mov al, ah
  2501.     out bel_prt, al        ; turn bell off
  2502.     ret            ; and return
  2503.  
  2504.  
  2505. ; Same thing, but a lower note ...
  2506.  
  2507.     PUBLIC Boop
  2508.  
  2509. Boop:    mov ax, beldiv        ; Pick up current value
  2510.     push ax            ; Save it
  2511.     shl ax, 1        ; Slide value left
  2512.     mov beldiv, ax        ; Store it in beldiv
  2513.     call Beep        ; Use the other routine
  2514.     pop WORD PTR beldiv    ; Get back the saved value
  2515.     ret
  2516.  
  2517.  
  2518. ; Restart escape sequence processing (hit new Esc)
  2519.  
  2520. Restart_esc_seq_processing:
  2521.     call Reset_esc_seq_reading ; Reset this guy ...
  2522.     jmp Do_Escape        ; Done with this one, start a new Esc seq
  2523.  
  2524.  
  2525. ; Here to add a character to the current line at the current position in
  2526. ;    the current rendition (as set up in Attribute_byte) ...  Advances
  2527. ;    Column and Char_Ptr unless in rightmost column, in which case the
  2528. ;    character is added but the position is not changed.
  2529. ;
  2530. ; call with
  2531. ;    al/ character to be added
  2532.  
  2533.     PUBLIC Add_this_char
  2534.  
  2535. Add_this_char:
  2536.     call Do_Graphic_Char    ; If we are in graphic mode, substitute
  2537.                 ;  proper graphic character for this one
  2538.  
  2539.     push ax            ; Save reg
  2540.     mov ax, Alloc_ds    ; Make es point to
  2541.     mov es, ax        ;  the allocated segment
  2542.     ASSUME es:Alloc
  2543.     pop ax            ; Restore reg
  2544.     mov bx, Char_Ptr    ; Ptr to char
  2545.     mov es:[bx], al        ; Store the char
  2546.     inc bx            ; Move to attr
  2547.     mov ah, Attribute_Byte    ; Current attr
  2548.     mov es:[bx], ah        ; Store it too
  2549.     inc bx            ; Bump ptr over it
  2550.     mov ax, Datas_ds    ; Make es point to
  2551.     mov es, ax        ;  the normal segment
  2552.     ASSUME es:Datas
  2553.  
  2554.     mov al, Column        ; Current column
  2555.     cmp al, Highest_column    ; In last column already?
  2556.      jne New_column        ;  No, go update ptrs
  2557.  
  2558.  
  2559. ; We were in the rightmost column, and we just wrote a character ...
  2560. ;  So, if we are in AutoWrap mode then we now need to do a CrLf
  2561.  
  2562.     cmp AutoWrap, 0        ; In AutoWrap mode?
  2563.      jz Say_changed        ;  No, leave alone
  2564.  
  2565.     mov Column, 0        ; Simulate a Cr, the column is now zero
  2566.     mov ax, Line_Ptr    ; Get line ptr
  2567.     mov Char_Ptr, ax    ; Store as new char ptr
  2568.     call Move_down_scroll_up ; Call the linefeed routine
  2569.     jmp SHORT Say_changed    ; Go finish up
  2570.  
  2571. New_column:
  2572.     mov Char_Ptr, bx    ; All ok, store new char ptr
  2573.     inc Column        ; Bump column number too, fall through to ...
  2574.  
  2575.  
  2576. ; Say that screen has changed, then return
  2577.  
  2578. Say_changed:
  2579.     or Screen_flags, Screen_changed ; Flag screen change
  2580.     ret            ; Done here
  2581.  
  2582.  
  2583. ; If the Graphi bit is on in our rendition, and the character is in the
  2584. ;  graphic character range, then substitute the PC's closest graphic ...
  2585.  
  2586. Do_Graphic_Char:
  2587.     test Rendition, Graphi    ; Are we in graphics mode?
  2588.      jz DGC_done        ;  No
  2589.  
  2590.     cmp al, 95        ; Check bottom of range
  2591.      jb DGC_done        ;  Too low to worry about
  2592.  
  2593.     cmp al, 126        ; Check top of range
  2594.      ja DGC_done        ;  Too high to worry about
  2595.  
  2596.     sub al, 95        ; Pull character into range
  2597.     mov bx, OFFSET Graphic_translation_table ; Addr of table to use
  2598.     xlat Graphic_translation_table ; Translate char into graphic
  2599.  
  2600. DGC_done:
  2601.     ret            ; Done here
  2602.  
  2603.  
  2604. ; Set new Tty graphic bit based on Char_set, G0_set and G1_set
  2605.  
  2606. NewAtr:    mov al, NOT Graphi    ; Get graphic bit
  2607.     and Rendition, al    ; Turn off bit for starters
  2608.  
  2609.     mov al, G0_set        ; Assume set zero
  2610.     mov ah, Char_set    ; Get which set we are in
  2611.     cmp ah, 0        ; Set 0?
  2612.      je Nw_1        ;  Yes ...
  2613.  
  2614.     mov al, G1_set        ; No, use set one
  2615.  
  2616. Nw_1:
  2617.     or Rendition, al    ; Set the bit accordingly
  2618.     ret            ;  and return
  2619.  
  2620.  
  2621. ; Move_down_scroll_up --  Go to or create a new line, moving downwards
  2622.  
  2623.     PUBLIC Move_down_scroll_up
  2624.  
  2625. Move_down_scroll_up:
  2626.     mov al, Row        ; Which row we are on
  2627.     cmp al, Bottom_margin    ; Are we on the bottom of the scrolling reg?
  2628.      je MDSU_2        ;  Yes, go deal with the scroll
  2629.  
  2630.     cmp al, Highest_row    ; Not bottom of scr reg, bot of screen?
  2631.      je MDSU_1        ;  Yes, go deal with non-case
  2632.  
  2633.     inc Row            ; Bump row number
  2634.     jmp Set_pointers    ; Get new ptrs, then done here
  2635.  
  2636. MDSU_1:    ret            ; Sequence to move down, can't ...
  2637.  
  2638. ; Scroll region up by one line ...
  2639.  
  2640. MDSU_2:    mov bl, Number_of_columns * 2 ; Number of bytes in a column
  2641.     mov al, bl        ; Create a working copy
  2642.     mul Top_margin        ; Multiply by row number of top margin
  2643.     add ax, OFFSET Screen_image ; Address screen
  2644.     mov di, ax        ; Install as destination
  2645.  
  2646.     sub bh, bh        ; Clear high half of word
  2647.     add ax, bx        ; Add in another line's worth
  2648.     mov si, ax        ; Install as source
  2649.  
  2650.     mov al, Bottom_margin    ; Start with bottom margin row number
  2651.     sub al, Top_margin    ; Number of lines to move
  2652.     mul bl            ; Multiply by number of bytes in a row
  2653.     shr ax, 1        ; Convert to number of words
  2654.     mov cx, ax        ; Install as repeat count
  2655.  
  2656.     mov ax, Alloc_ds    ; Set up ptrs to allocated segment in
  2657.     mov ds, ax        ;  ds and
  2658.     mov es, ax        ;  es
  2659.     ASSUME ds:Alloc, es:Alloc
  2660.  
  2661.     cld            ; Move forwards as we copy
  2662.     rep movsw        ; Scroll the region up by one row
  2663.  
  2664.     mov cx, Number_of_columns ; Number of words in a row
  2665.     mov ax, 0720h        ; Normal spaces
  2666.     rep stosw        ; Fill the new line with blanks
  2667.  
  2668.     mov ax, Datas_ds    ; Return segment ptrs to normal
  2669.     mov ds, ax
  2670.     mov es, ax
  2671.     ASSUME ds:Datas, es:Datas
  2672.  
  2673.     inc Number_of_scrolls_done ; Keep track for early quit
  2674.     or Screen_flags, Screen_changed ; Flag screen change
  2675.     ret            ; Done here
  2676.  
  2677.  
  2678. ; Move_up_scroll_down --  Go to or create a new line, moving upwards
  2679.  
  2680.     PUBLIC Move_up_scroll_down
  2681.  
  2682. Move_up_scroll_down:
  2683.     mov al, Row        ; The row we are on
  2684.     cmp al, Top_margin    ; Are we in the top row of the scrolling reg?
  2685.      je MUSD_2        ;  Yes, go deal with the scroll
  2686.  
  2687.     or al, al        ; Already as high as we can go?
  2688.      jz MUSD_1        ;  Yes, go deal with non-case
  2689.  
  2690.     dec Row            ; Bump row number
  2691.     jmp Set_pointers    ; Get new ptrs, then done here
  2692.  
  2693. MUSD_1:    ret            ; Sequence to move up, can't ...
  2694.  
  2695. ; Scroll region down by one line ...
  2696.  
  2697. MUSD_2:    mov bl, Number_of_columns * 2 ; Number of bytes in a column
  2698.     mov al, bl        ; Create a working copy
  2699.     mul Bottom_margin    ; Multiply by row number of bottom margin
  2700.     add ax, OFFSET Screen_image + (Highest_column * 2)
  2701.                 ; Address last word in the line
  2702.     mov di, ax        ; Install as destination
  2703.  
  2704.     sub bh, bh        ; Clear high half of word
  2705.     sub ax, bx        ; Subtract out another line's worth
  2706.     mov si, ax        ; Install as source
  2707.  
  2708.     mov al, Bottom_margin    ; Start with bottom margin row number
  2709.     sub al, Top_margin    ; Number of lines to move
  2710.     mul bl            ; Multiply by number of bytes in a row
  2711.     shr ax, 1        ; Convert to number of words
  2712.     mov cx, ax        ; Install as repeat count
  2713.  
  2714.     mov ax, Alloc_ds    ; Set up ptrs to allocated segment in
  2715.     mov ds, ax        ;  ds and
  2716.     mov es, ax        ;  es
  2717.     ASSUME ds:Alloc, es:Alloc
  2718.  
  2719.     std            ; Move backwards as we copy
  2720.     rep movsw        ; Scroll the region down by one row
  2721.  
  2722.     mov cx, Number_of_columns ; Number of words in a row
  2723.     mov ax, 0720h        ; Normal spaces
  2724.     rep stosw        ; Fill the new line with blanks
  2725.  
  2726.     mov ax, Datas_ds    ; Return segment ptrs to normal
  2727.     mov ds, ax
  2728.     mov es, ax
  2729.     ASSUME ds:Datas, es:Datas
  2730.  
  2731.     inc Number_of_scrolls_done ; Keep track for early quit
  2732.     or Screen_flags, Screen_changed ; Flag screen change
  2733.     ret            ; Done here
  2734.  
  2735.  
  2736. ; Return skip ...
  2737.  
  2738. RSkp    PROC
  2739.  
  2740.     pop bx            ; Pick up return address
  2741.     add bx, 3        ; Bump up by 3
  2742.     push bx            ; Back on the stack
  2743.     ret            ; Then just return ...
  2744.  
  2745. RSkp    ENDP
  2746.  
  2747.  
  2748. ; Set attribute byte based on rendition
  2749.  
  2750.     PUBLIC Set_attribute_byte
  2751.  
  2752. Set_attribute_byte:
  2753.     mov al, Rendition    ; Load the current VT100 graphic rendition
  2754.     and al, Bold+Underscored+Blinking+Inverted ; Keep only these bits
  2755.     mov bx, OFFSET Color_attributes ; Addr of rend-to-attribute table
  2756.     xlat Color_attributes    ; Translate rendition to attribute
  2757.     mov Attribute_byte, al    ; Set up attribute
  2758.     ret            ; Done here
  2759.  
  2760.  
  2761. ;   call PullCh
  2762. ;    Used to get the backed-up char, if any, or a character from the
  2763. ;    escape buffer, if any, else from the port, if any ...  returns skip
  2764. ;    if a character was found ... 
  2765. ;
  2766. ;   Returns ... 
  2767. ;    +1 if no char to be found
  2768. ;    +2 if found a char (from either buffer), char is in al
  2769.  
  2770.     PUBLIC PullCh
  2771.  
  2772. PullCh    PROC
  2773.  
  2774.     mov al, Backed_up_char    ; Get the backed-up char
  2775.     cmp al, 0        ; Did we get one?
  2776.      je PCH_1        ;  No, get a new char
  2777.  
  2778.     mov Backed_up_char, 0    ; Clear char for next time
  2779.     RetSkp            ; Go RetSkp
  2780.  
  2781. PCH_1:    mov bx, EBufGt        ; Escape buf getter ptr
  2782.     cmp bx, EBufPt        ; Compare with putter ptr
  2783.      je PCH_2        ;  If same, no chars held there
  2784.  
  2785.     mov al, [bx]        ; Pick up the char
  2786.     inc EBufGt        ; Bump the ptr
  2787.     jmp SHORT PCH_End    ; Go finish up
  2788.  
  2789. PCH_2:    call Get_char_from_port    ; See if another char is available
  2790.      jnc PCH_Ret        ;  If no char, just return
  2791.  
  2792. ; We just got a char from the host, so if we are running under control of a
  2793. ;  script we need to let the script processor know what that character is.
  2794.  
  2795.     cmp Script_processor, 0    ; Is there a script processor to run?
  2796.      je PCH_No_script    ;  No
  2797.  
  2798.     mov ah, 1        ; Code for "character" entry
  2799.     call Script_processor    ; Let it do its thing
  2800.  
  2801. PCH_No_script:
  2802.     test flags, capt    ; capturing output?
  2803.      jz PCH_4        ; no, forget this part
  2804.  
  2805.     push ax            ; save char
  2806.     call captrtn        ; give it captured character
  2807.     pop ax            ; restore character and keep going
  2808.  
  2809. PCH_4:    or al, al        ; Is the char a null?
  2810.      jz PCH_2        ;  Got a null, go try again
  2811.  
  2812.     cmp al, DEL        ; Or delete?
  2813.      je PCH_2        ;  Yes, ignore this char and try again
  2814.  
  2815.     cmp al, 'X'-100q    ; Control-X?
  2816.      je PCH_Abort        ;  Yes, blow out esc seq
  2817.  
  2818.     cmp al, 'Z'-100q    ; Control-Z?
  2819.      je PCH_Abort        ;  Yes, blow out esc seq
  2820.  
  2821.     call Store_char_in_esc_buffer ; Store the char in the escape buffer
  2822.  
  2823. PCH_End:
  2824.     mov Previous_char, al    ; Save the char
  2825.     RetSkp            ; Return with the char
  2826.  
  2827. PCH_Abort:
  2828.     mov al, 177        ; Char decimal 177 is the IBM display char
  2829.                 ;  most closely corresponding to VT100's
  2830.                 ;  error blot ... half dots on ...
  2831.     call Add_this_char    ; Write the character to the screen
  2832.     jmp Abort_esc_sequence    ; ^X and ^Z will halt any esc sequence ...
  2833.  
  2834. PCH_Ret: ret            ; No char to get, just return
  2835.  
  2836. PullCh    ENDP
  2837.  
  2838.  
  2839. ;   call Store_char_in_esc_buffer
  2840. ;    Store a new character in the escape buffer for later rereading
  2841.  
  2842.     PUBLIC Store_char_in_esc_buffer
  2843.  
  2844. Store_char_in_esc_buffer PROC
  2845.  
  2846.     mov ah, EBufCt        ; Pick up count of chars so far
  2847.     cmp ah, EBufLn-1    ; Is the buffer full?
  2848.      jge Stc_E        ;  Full, give up
  2849.  
  2850.     mov di, EBufPt        ; Get putter ptr
  2851.     cld            ; Forwards
  2852.     stosb            ; Store char in buffer
  2853.     mov EBufPt, di        ; Store updated putter ptr
  2854.     mov EBufGt, di        ; Store as getter ptr also to prevent rereading
  2855.     inc EBufCt        ; Bump count of chars in buffer
  2856.  
  2857. Stc_E:    ret
  2858.  
  2859. Store_char_in_esc_buffer ENDP
  2860.  
  2861.  
  2862. ;   call UnPull
  2863. ;    Used to back up the pull sequence by one character
  2864.  
  2865. UnPull    PROC
  2866.  
  2867.     mov al, Previous_char    ; Pick up the last char
  2868.     mov Backed_up_char, al    ; Save it as the backed-up char
  2869.     ret            ;  and return
  2870.  
  2871. UnPull    ENDP
  2872.  
  2873.  
  2874. ; PulNum -- Use PullCh to read a number
  2875.  
  2876. ;   call PulNum
  2877. ;    Used to read in a number using PullCh
  2878.  
  2879. ;   Returns ... 
  2880. ;    +1 if hit eof on call to PullCh
  2881. ;    +2 if got a number, number in dl
  2882.  
  2883.     PUBLIC PulNum
  2884.  
  2885. PulNum:    sub dl, dl        ; First clear dl
  2886.  
  2887. PN_1:    call PullCh        ; Get a char
  2888.      RetNop            ;  No
  2889.  
  2890.     cmp al, '0'        ; Lower than 0?
  2891.      jl PN_2        ;  Yes, done here
  2892.  
  2893.     cmp al, '9'        ; Higher than 9?
  2894.      jg PN_2        ;  Yes, done here
  2895.  
  2896.     sub al, '0'        ; Make ASCII digit into decimal
  2897.     xchg al, dl        ; Swap al and dl
  2898.     mov bl, 10        ; Get a ten
  2899.     mul bl            ; Multiply old number by ten
  2900.     add dl, al        ; Add in the new digit
  2901.     jmp PN_1        ; Go get another char
  2902.  
  2903. PN_2:    call UnPull        ; Release the char we just read
  2904.     RetSkp            ; Tell caller he has a number
  2905.  
  2906.  
  2907. ; Get_numeric_params -- Get Vt100 Escape sequence numbers ...
  2908.  
  2909.     PUBLIC Get_numeric_params
  2910.  
  2911. Get_numeric_params:
  2912.     sub ax, ax        ; Get a zero
  2913.     mov NumCnt, al        ; Clear count
  2914.     mov NumPtr, al        ;  and ptr
  2915.  
  2916. GNP_1:    call PulNum        ; Try to get a number
  2917.      RetNop            ;  No
  2918.  
  2919.     call PullCh        ; Get the number's terminating char
  2920.      RetNop            ;  No
  2921.  
  2922.     inc NumCnt        ; Bump count of args
  2923.     mov bl, NumCnt        ; Copy to bx
  2924.     sub bh, bh        ; Clear high half
  2925.     mov Nums-1[bx], dl    ; Store the number we got from PulNum
  2926.  
  2927.     cmp al, ';'        ; Was terminator a semi-colon?
  2928.      je GNP_1        ;  Yes, go get another argument ...
  2929.  
  2930.     call UnPull        ; Un-get char so the other routine can get it
  2931.     RetSkp            ;  and return nicely ...
  2932.  
  2933.  
  2934. ; Get_next_number -- Get a single number from previously stored numbers
  2935.  
  2936.     PUBLIC Get_next_number
  2937.  
  2938. Get_next_number:
  2939.     inc NumPtr        ; Bump ptr
  2940.     mov bl, NumPtr        ; Get ptr into low half
  2941.     cmp bl, NumCnt        ; Off end of list?
  2942.      jle GNN_1        ;  No, keep going
  2943.  
  2944.     ret            ; No more, done here
  2945.  
  2946. GNN_1:    sub bh, bh        ; Zero high half
  2947.     mov al, Nums-1[bx]    ; Get the next number
  2948.     RetSkp            ; Tell caller he has a number ...
  2949.  
  2950.  
  2951. ; Get a single numeric parameter, default is zero if no parameters.
  2952.  
  2953.     PUBLIC Default_zero
  2954.  
  2955. Default_zero:
  2956.     call Get_next_number    ; Pick up next arg, if any
  2957.      jmp SHORT D0_1        ;  No more, go take default
  2958.      nop            ; 3 bytes ...
  2959.  
  2960.     ret            ; Got one, use it
  2961.  
  2962. D0_1:    sub al, al        ; Default to 0
  2963.     ret            ; Done here
  2964.  
  2965.  
  2966. ; Get a single numeric parameter, default is one (if param is zero
  2967. ;  or if there is no parameter).
  2968.  
  2969.     PUBLIC Default_one
  2970.  
  2971. Default_one:
  2972.     call Get_next_number    ; Pick up next arg, if any
  2973.      jmp SHORT D1_1        ;  No more, go take default
  2974.      nop            ; 3 bytes ...
  2975.  
  2976.     or al, al        ; Is it zero?
  2977.      jnz D1_2         ;  No, go use it
  2978.  
  2979. D1_1:    mov al, 1        ; Default to 1
  2980.  
  2981. D1_2:    ret            ; Done here
  2982.  
  2983.  
  2984. ; Set up to run a script processor at selected times, or clear it with zero
  2985.  
  2986. Set_up_script_processor_PC:
  2987.  
  2988.     mov Script_Processor, ax ; Set this up, or zero it out
  2989.     ret            ; That was easy
  2990.  
  2991.  
  2992. ; Convert an integer into its decimal ASCII representation in memory
  2993.  
  2994. ; Call with
  2995. ;    ax/ number to be converted
  2996. ;    di/ ptr to area to write the string
  2997.  
  2998. Nout:    sub dx, dx        ; Make a zero
  2999.     mov bx, 10        ; Get a ten
  3000.     div bx            ; Divide ax by ten
  3001.     push dx            ; Save remainder
  3002.     or ax, ax        ; Quotient zero?
  3003.      jz Nout_1        ;  Yes, don't dig deeper
  3004.  
  3005.     call Nout        ; Recursively get the rest of the number
  3006.  
  3007. Nout_1:    pop ax            ; Get back saved digit
  3008.     add al, '0'        ; Convert this digit
  3009.     stosb            ; Put it into the output area
  3010.     ret            ; Done at this level
  3011.  
  3012. VT100_Utilities ENDP
  3013.  
  3014.  
  3015. ;******************************************************************************
  3016.  
  3017. ; *Character handling routines ...
  3018.  
  3019. ; Some control characters ...
  3020.  
  3021. Ctrl_Ch    PROC
  3022.  
  3023.  
  3024. ; Bell
  3025.  
  3026. Do_Bell:
  3027.     call Beep        ; Beep the bell
  3028.     jmp Done_with_char
  3029.  
  3030.  
  3031. ; Tab
  3032.  
  3033. Do_Tab:    mov al, Column        ; Get current column #
  3034.     or al, 7        ; Go to next tab stop
  3035.     inc al            ; Fancy trick ...
  3036.     cmp al, Highest_column     ; Too high?
  3037.      jle Dot_2        ;  No
  3038.  
  3039.     mov al, Highest_column    ; Truncate to width ...
  3040.  
  3041. Dot_2:    mov Column, al        ; Save new column number
  3042.     jmp Set_ptrs_then_done
  3043.  
  3044.  
  3045. ; Backspace
  3046.  
  3047. Do_Bs:    dec Column        ; Decr the column
  3048.      jns Dob_1        ;  Is it now negative?
  3049.  
  3050.     mov Column, 0        ; Set col to zero
  3051.  
  3052. Dob_1:    jmp Set_ptrs_then_done    ; Set up new pointers
  3053.  
  3054.  
  3055. ; Carriage return
  3056.  
  3057. Do_Cr:    mov Column, 0        ; Column is now zero
  3058.     mov ax, Line_Ptr    ; Get line ptr
  3059.     mov Char_Ptr, ax    ; Store as new char ptr
  3060.     or Screen_flags, Position_changed ; Flag screen change
  3061.     jmp Done_with_char
  3062.  
  3063.  
  3064. ; Shift out
  3065.  
  3066. Do_SO:    mov al, 1        ; Get a one
  3067.     jmp SHORT DoSI_1    ; Join common code
  3068.  
  3069.  
  3070. ; Shift in
  3071.  
  3072. Do_SI:    sub al, al        ; Clear al
  3073. DoSI_1:    mov Char_set, al    ; Put us in the G0 charset
  3074.     call NewAtr        ; Go set up a new attr based on this
  3075.     jmp Done_with_char
  3076.  
  3077. Ctrl_Ch    ENDP
  3078.  
  3079.  
  3080. ; Escape ...
  3081.  
  3082.     PUBLIC Do_escape
  3083.  
  3084. Do_Escape PROC
  3085.  
  3086.     call PullCh        ; Try to get a char
  3087.      jmp No_more_chars    ;  No more chars, try again later
  3088.  
  3089.     mov bx, OFFSET ActTb2    ; Action table
  3090.     mov cx, NChrTb2        ; Number of chars to check
  3091.     mov dx, OFFSET ChrTb2    ; The character table
  3092.     jmp Check_Table        ; Go dispatch to the right routine
  3093.  
  3094. Do_Escape ENDP
  3095.  
  3096.  
  3097. ; Hit Escape left square bracket ($[), keep checking ...
  3098.  
  3099.     PUBLIC Do_left_square
  3100.  
  3101. Do_left_square PROC
  3102.  
  3103.     call PullCh        ; Look at the next char
  3104.      jmp No_more_chars    ;  No more chars, try again later
  3105.  
  3106.     or VT100_status_flags, Private_esc_seq ; Assume private esc sequence
  3107.  
  3108.     cmp al, '?'        ; Hit qmark?
  3109.      je DSQ_1        ;  Yes, "eat" it
  3110.  
  3111.     call UnPull        ; Not qmark, get it back for Get_numeric_params
  3112.     and VT100_status_flags, NOT Private_esc_seq ; Not private esc sequence
  3113.  
  3114. DSQ_1:    call Get_numeric_params    ; Get numeric parameters, if any
  3115.      jmp No_more_chars    ;  Bomb
  3116.  
  3117.     call PullCh        ; Get the closing char of the sequence
  3118.      jmp No_more_chars    ;  No more chars, try again later
  3119.  
  3120.     test VT100_status_flags, Printer_controller_mode
  3121.      jz DSQ_2        ;  Not in funny mode, continue as usual
  3122.  
  3123.     cmp al, 'i'        ; Only seq that gets us out of funny mode ..
  3124.      je DSQ_2        ;  That's it, go run with it
  3125.  
  3126.     jmp Done_with_char    ; In funny mode, not seq to leave it, ignore
  3127.  
  3128. DSQ_2:    mov bx, OFFSET ActTb3    ; Action table
  3129.     mov cx, NChrTb3        ; Number of chars to check
  3130.     mov dx, OFFSET ChrTb3    ; The character table
  3131.     jmp Check_Table        ; Go dispatch to the right routine
  3132.  
  3133. Do_left_square ENDP
  3134.  
  3135.  
  3136. ; Saw Escape left paren ... 
  3137.  
  3138. Do_left_paren    PROC
  3139.  
  3140.     call PullCh        ; Get next char
  3141.      jmp No_more_chars    ;  No more chars, try again later
  3142.  
  3143.     test VT100_status_flags, Printer_controller_mode
  3144.      jz LFP_1        ;  Not in funny mode, continue as usual
  3145.  
  3146.     jmp Done_with_char    ; In funny mode, not seq to leave it, ignore
  3147.  
  3148. LFP_1:    mov bx, OFFSET ActTb4    ; Action table
  3149.     mov cx, NChrTb4        ; Number of chars to check
  3150.     mov dx, OFFSET ChrTb4    ; The character table
  3151.     jmp Check_Table        ; Go dispatch to the right routine
  3152.  
  3153. Lfp_B:    sub al, al        ; Get a zero
  3154.     jmp SHORT Lfp_Mr    ; Join common code
  3155.  
  3156. Lfp_0:    mov al, Graphi        ; Get graphic bit
  3157.  
  3158. Lfp_Mr:    mov G0_set, al        ; Set G0 charset to whatever
  3159.     call NewAtr        ; Set it up
  3160.     jmp Done_with_char
  3161.  
  3162. Do_left_paren    ENDP
  3163.  
  3164.  
  3165. ; Saw Escape right paren ... 
  3166.  
  3167. Do_right_paren    PROC
  3168.  
  3169.     call PullCh        ; Get next char
  3170.      jmp No_more_chars    ;  No more chars, try again later
  3171.  
  3172.     test VT100_status_flags, Printer_controller_mode
  3173.      jz RTP_1        ;  Not in funny mode, continue as usual
  3174.  
  3175.     jmp Done_with_char    ; In funny mode, not seq to leave it, ignore
  3176.  
  3177. RTP_1:    mov bx, OFFSET ActTb5    ; Action table
  3178.     mov cx, NChrTb5        ; Number of chars to check
  3179.     mov dx, OFFSET ChrTb5    ; The character table
  3180.     jmp Check_Table        ; Go dispatch to the right routine
  3181.  
  3182. Rtp_B:    sub al, al        ; Get a zero
  3183.     jmp SHORT Rtp_Mr    ; Join common code
  3184.  
  3185. Rtp_0:    mov al, Graphi        ; Get graphic bit
  3186.  
  3187. Rtp_Mr:    mov G1_set, al        ; Set G1 charset to whatever
  3188.     call NewAtr        ; Set it up
  3189.     jmp Done_with_char
  3190.  
  3191. Do_right_paren    ENDP
  3192.  
  3193.  
  3194. ; Saw Escape pound sign ... 
  3195.  
  3196. Do_pound_sign PROC
  3197.  
  3198.     call PullCh        ; Get next char
  3199.      jmp No_more_chars    ;  No more chars, try again later
  3200.  
  3201.     cmp al, Esc        ; Escape?
  3202.      je DOP_1        ;  Yes, do the decent thing
  3203.  
  3204.     jmp Done_with_char    ; These are all not supported yet ...
  3205.  
  3206. DOP_1:    jmp Restart_esc_seq_processing ; Go get a new escape sequence
  3207.  
  3208. Do_pound_sign ENDP
  3209.  
  3210.  
  3211. ;***************************************************************************
  3212.  
  3213. ; *VT100 Escape Sequences as described in VT100 User Guide* ...
  3214.  
  3215. VT100_Routines PROC
  3216.  
  3217. ; Cursor Backward
  3218.  
  3219. CUB:    call Default_one    ; Get argument, default to one
  3220.  
  3221.     mov ah, Column        ; Get current column
  3222.     sub ah, al        ; Back it up by requested # columns
  3223.      jns CUB_1        ;  Is it now negative?
  3224.  
  3225.     sub ah, ah        ; Make a zero
  3226.  
  3227. CUB_1:    mov Column, ah        ; Set column to new value
  3228.     jmp SHORT Set_ptrs_then_done
  3229.  
  3230.  
  3231. ; Cursor Down
  3232.  
  3233. CUD:    call Default_one    ; Pick up the arg, default to 1
  3234.  
  3235.     mov ah, Row        ; Get current row
  3236.     add ah, al        ; Add in requested # rows
  3237.     mov al, Highest_row    ; Maximum offset for row number
  3238.     cmp ah, al        ; Is new row number too high?
  3239.      jbe CUD_1        ;  All is OK ...
  3240.  
  3241.     mov ah, al        ; Use the maximum
  3242.  
  3243. CUD_1:    mov Row, ah        ; Update the row
  3244.     jmp SHORT Set_ptrs_then_done
  3245.  
  3246.  
  3247. ; Cursor Forward
  3248.  
  3249. CUF:    call Default_one    ; Pick up the arg, default to 1
  3250.  
  3251.     mov ah, Column        ; Get current column
  3252.     add ah, al        ; Add in requested # columns
  3253.     mov al, Highest_column    ; Maximum offset
  3254.     cmp ah, al        ; Is new column number too high?
  3255.      jbe CUF_1        ;  All is OK ...
  3256.  
  3257.     mov ah, al        ; Use the maximum
  3258.  
  3259. CUF_1:    mov Column, ah        ; Update the column
  3260.     jmp SHORT Set_ptrs_then_done
  3261.  
  3262.  
  3263. ; Cursor Position
  3264.  
  3265.     PUBLIC CUP
  3266.  
  3267. CUP:    call Default_one    ; Pick up the first arg, default to 1
  3268.     dec al            ; Make it an offset
  3269.      jns CUP_1        ;  Not negative, move on
  3270.  
  3271.     sub al, al        ; Make it zero
  3272.  
  3273. CUP_1:    mov ah, Highest_row    ; Maximum offset
  3274.     cmp al, ah        ; Is requested row number too high?
  3275.      jbe CUP_2        ;  In range, move on
  3276.  
  3277.     mov al, ah        ; Use the maximum
  3278.  
  3279. CUP_2:    mov NewRow, al        ; Save as new row number
  3280.  
  3281.     call Default_one    ; Pick up the second arg, default to 1
  3282.     dec al            ; Make it an offset
  3283.      jns CUP_3        ;  Not negative, move on
  3284.  
  3285.     sub al, al        ; Make it zero
  3286.  
  3287. CUP_3:    mov ah, Highest_column    ; Maximum offset
  3288.     cmp al, ah        ; Is requested column number too high?
  3289.      jbe CUP_4        ;  In range, move on
  3290.  
  3291.     mov al, ah        ; Use the maximum
  3292.  
  3293. CUP_4:    mov Column, al        ; Save as new column number
  3294.  
  3295.     mov al, NewRow        ; Load up the requested row number
  3296.     mov Row, al        ; Store it
  3297.  
  3298.     jmp SHORT Set_ptrs_then_done
  3299.  
  3300.  
  3301. ; Cursor Up
  3302.  
  3303. CUU:    call Default_one    ; Get argument, default to one
  3304.  
  3305.     mov ah, Row        ; Get current row
  3306.     sub ah, al        ; Back it up by requested # rows
  3307.      jns CUU_1        ;  Is it now negative?
  3308.  
  3309.     sub ah, ah        ; Make a zero
  3310.  
  3311. CUU_1:    mov Row, ah        ; Set row to new value
  3312.  
  3313. ; Fall thru to Set_ptrs_then_done ...
  3314.  
  3315. ; Common finish up point for cursor positioning routines
  3316.  
  3317. Set_ptrs_then_done:
  3318.     call Set_pointers    ; Set up new pointers
  3319.     jmp Done_with_char    ; Then are are done
  3320.  
  3321.  
  3322. ; Device Attributes
  3323.  
  3324. DA:    test VT100_status_flags, Private_esc_seq ; Include a "?" ?
  3325.      jnz DA_ignore        ;  Yes, don't answer it
  3326.  
  3327.     call Default_zero    ; Get parameter, if any
  3328.  
  3329.     or al, al        ; Is it zero?
  3330.      jnz DA_ignore        ;  No, just ignore it
  3331.  
  3332.     mov si, OFFSET DA_Str    ; What to send ...
  3333.     call Send_str_to_port ; Send the string to the port
  3334.  
  3335. DA_ignore:
  3336.     jmp Done_with_char
  3337.  
  3338.  
  3339. ; DEC (private) terminal ID
  3340.  
  3341. DECID:    jmp DA            ; Same thing
  3342.  
  3343.  
  3344. ; DEC (private) Keypad Application Mode
  3345.  
  3346. DECKPAM:
  3347.     or VT100_status_flags, Keypad_application_mode ; Turn on the flag
  3348.     jmp Done_with_char
  3349.  
  3350.  
  3351. ; DEC (private) Keypad Numeric Mode
  3352.  
  3353. DECKPNM:
  3354.     and VT100_status_flags, NOT Keypad_application_mode ; Turn off the flag
  3355.     jmp Done_with_char
  3356.  
  3357.  
  3358. ; DEC (private) Load LEDs
  3359.  
  3360.     PUBLIC DECLL
  3361.  
  3362. DECLL:    call Default_zero    ; Get the first parameter, default zero
  3363.  
  3364. DECLL_Loop:
  3365.     cmp al, 4        ; Highest value we have code for
  3366.      jg DECLL_Ignore    ; Can't handle it
  3367.  
  3368.     cbw            ; Blow up to full word
  3369.     shl ax, 1        ; Double offset for words
  3370.     mov bx, ax        ; Copy to bx
  3371.     jmp DECLL_Table[bx]    ; Dispatch thru table to correct routine
  3372.  
  3373. DECLL_0:
  3374.     mov al, NOT (LED1 + LED2 + LED3 + LED4)
  3375.     and LEDs, al        ; Turn off those bits ... 
  3376.     jmp SHORT DECLL_Ignore    ; Done with this part
  3377.  
  3378. DECLL_1:
  3379.     mov al, LED1        ; Flag for LED # 1
  3380.     jmp SHORT DECLL_Set    ; Go set the bit
  3381.  
  3382. DECLL_2:
  3383.     mov al, LED2        ; Flag for LED # 2
  3384.     jmp SHORT DECLL_Set    ; Go set the bit
  3385.  
  3386. DECLL_3:
  3387.     mov al, LED3        ; Flag for LED # 3
  3388.     jmp SHORT DECLL_Set    ; Go set the bit
  3389.  
  3390. DECLL_4:
  3391.     mov al, LED4        ; Flag for LED # 4
  3392.  
  3393. DECLL_Set:
  3394.     or LEDs, al        ; Set the bit
  3395.  
  3396. DECLL_Ignore:
  3397.     call Get_next_number    ; Try to get another number
  3398.      jmp SHORT DECLL_Done    ;  No such luck ... 
  3399.      nop            ;  3 bytes
  3400.  
  3401.     jmp DECLL_Loop        ; Got one, go do something with it
  3402.  
  3403. DECLL_Done:
  3404.     mov Prev_shift_state, 0FFh ; Force set up of new mode line
  3405.     jmp Done_with_char    ; Done with this one
  3406.  
  3407.  
  3408. ; DEC (private) Restore Cursor
  3409.  
  3410. DECRC:    mov al, Save_char_set    ; Pick up which set we were in
  3411.     mov Char_set, al    ; Restore it
  3412.  
  3413.     mov al, Save_G0_set    ; Pick up saved char set
  3414.     mov G0_set, al        ; Restore it
  3415.  
  3416.     mov al, Save_G1_set    ; Pick up saved char set
  3417.     mov G1_set, al        ; Restore it
  3418.  
  3419.     mov al, Save_rendition    ; Pick up rendition
  3420.     mov Rendition, al    ; Restore it
  3421.  
  3422.     mov ax, Save_position    ; Pick up old cursor position
  3423.     mov Cursor_position, ax    ; Restore it
  3424.  
  3425.     jmp Set_ptrs_then_done ; Get a new ptr to the line we are on, done
  3426.  
  3427.  
  3428. ; DEC (private) Save Cursor
  3429.  
  3430. DECSC:    mov al, Char_set    ; Pick this up
  3431.     mov Save_char_set, al    ; Save it
  3432.  
  3433.     mov al, G0_set        ; Pick this up
  3434.     mov Save_G0_set, al    ; Save it
  3435.  
  3436.     mov al, G1_set        ; Pick this up
  3437.     mov Save_G1_set, al    ; Save it
  3438.  
  3439.     mov al, Rendition    ; Pick this up
  3440.     mov Save_rendition, al    ; Save it
  3441.  
  3442.     mov ax, Cursor_position    ; Pick this up
  3443.     mov Save_position, ax    ; Save it
  3444.  
  3445.     jmp Set_ptrs_then_done ; Get a new ptr to the line we are on, done
  3446.  
  3447.  
  3448. ; DEC (private) Set Top and Bottom Margins
  3449.  
  3450.     PUBLIC DECSTBM
  3451.  
  3452. DECSTBM:
  3453.     call Default_one    ; Try to get the top margin, def is 1
  3454.  
  3455.     dec al            ; Change to offset
  3456.     mov Top_margin, al    ; Store it
  3457.  
  3458.     call Default_zero    ; Try to get bottom margin, use zero for now
  3459.  
  3460.     or al, al        ; Was it zero?
  3461.      jnz DST_1        ;  No, use what we got
  3462.  
  3463.     mov al, Number_of_rows    ; Default to number of rows on screen
  3464.  
  3465. DST_1:    dec al            ; Change to offset
  3466.     mov Bottom_margin, al    ; Store the margin we got
  3467.  
  3468. ; This Esc sequence puts us in the home position ... 
  3469.  
  3470.     sub ax, ax        ; Get a zero
  3471.     mov Cursor_position, ax ; Move to upper left corner
  3472.     jmp Set_ptrs_then_done    ; Set pointers, done with this char
  3473.  
  3474.  
  3475. ; Device Status Report
  3476.  
  3477. DSR:    call Get_next_number    ; Get a number
  3478.      jmp SHORT DSR_1    ;  If no number, default to 5
  3479.      nop            ;  3 bytes
  3480.  
  3481.     cmp al, 5        ; Is it five?
  3482.      jne DSR_2        ;  No, see what it is
  3483.  
  3484. DSR_1:    mov si, OFFSET DSR_str    ; Load up ptr to string we want to send
  3485.     call Send_str_to_port    ; Send it
  3486.     jmp Done_with_char
  3487.  
  3488. DSR_2:    cmp al, 6        ; Is it six?
  3489.      jne DSR_End        ;  No, then don't know what to do anyway
  3490.  
  3491.     mov si, OFFSET CPR_str    ; Load ptr to string
  3492.     call Send_str_to_port ; Send it
  3493.  
  3494.     mov al, Row        ; Pick up row number
  3495.     cbw            ; Convert to word
  3496.     inc ax            ; Row and col numbers start at 1, not zero
  3497.     mov di, OFFSET LoWork    ; Ptr to work area
  3498.     push di            ; Save it
  3499.     call Nout        ; Write number to work area
  3500.     sub al, al        ; Make a zero
  3501.     stosb            ; Tie off the string
  3502.     pop si            ; Get back ptr into si
  3503.     call Send_str_to_port    ; Send the string along
  3504.  
  3505.     mov al, ';'        ; A semicolon
  3506.     call Send_char_to_port    ; Type it
  3507.  
  3508.     mov al, Column        ; Pick up column number
  3509.     cbw            ; Convert to word
  3510.     inc ax            ; Row and col numbers start at 1, not zero
  3511.     mov di, OFFSET LoWork    ; Ptr to work area
  3512.     push di            ; Save it
  3513.     call Nout        ; Write number to work area
  3514.     sub al, al        ; Make a zero
  3515.     stosb            ; Tie off the string
  3516.     pop si            ; Get back ptr into si
  3517.     call Send_str_to_port    ; Send the string along
  3518.  
  3519.     mov al, 'R'        ; A capital R
  3520.     call Send_char_to_port    ; Send to port, return from there
  3521.  
  3522. DSR_End: jmp Done_with_char    ; Can't deal with it ...
  3523.  
  3524.  
  3525. ; Erase in Display
  3526.  
  3527.     PUBLIC ED
  3528.  
  3529. ED:    call Default_zero    ; Get a param
  3530.  
  3531.     cmp al, 17        ; Is it our "magic" value?
  3532.      je ED_Magic        ;  It is ...
  3533.  
  3534.     cmp al, 18        ; Code to identify ourselves (non-VT100)?
  3535.      je ED_Identify        ;  It is ...
  3536.  
  3537.     cmp al, 19        ; Code to quit to command mode?
  3538.      je ED_Command        ;  It is ...
  3539.  
  3540.     cmp al, 20        ; Code to quit to DOS?
  3541.      je ED_Exit_to_DOS    ;  It is ...
  3542.  
  3543.     cmp al, 21        ; Code to preload a command?
  3544.      je ED_Preload        ;  It is ...
  3545.  
  3546.     cmp al, 2        ; Is it too high?
  3547.      jg ED_ignore        ;  Yes ...
  3548.  
  3549.     cbw            ; Blow up to full word
  3550.     shl ax, 1        ; Double offset for words
  3551.     mov bx, ax        ; Copy to bx
  3552.     jmp ED_Table[bx]    ; Dispatch thru table to correct routine
  3553.  
  3554. ED_Magic:
  3555.     call Go_to_page_zero    ; Go to base page
  3556.     call Enter_Server    ; Jump suddenly into Server mode
  3557.      nop            ;  Skips on success
  3558.      nop
  3559.      nop
  3560.     call SerIni_PC        ; In case port got turned off
  3561.     or Screen_flags, Force_screen_update ; Update the world
  3562.     call Do_our_screen    ; Restore our screen
  3563.     jmp SHORT ED_ignore
  3564.  
  3565. ED_Identify:
  3566.     mov si, OFFSET Ident_str ; What to send ...
  3567.     call Send_str_to_port    ; Send the string to the port
  3568.     jmp SHORT ED_ignore
  3569.  
  3570. ED_Command:
  3571.     call Leave_emulator
  3572.     jmp SHORT ED_ignore
  3573.  
  3574. ED_Exit_to_DOS:
  3575.     call Leave_program
  3576.     jmp SHORT ED_ignore
  3577.  
  3578. ED_Preload:
  3579.     sub cx, cx        ; Zero characters preloaded so far
  3580.     mov di, OFFSET Preload_buffer ; Point at the start of our buffer
  3581.     cld            ; Forwards
  3582.  
  3583. ED_ploop:
  3584.     push di            ; Save register just in case
  3585.  
  3586.     call PullCh        ; Get a new character
  3587.      jmp ED_p_no_more    ;  No such luck
  3588.  
  3589.     pop di            ; Restore register
  3590.  
  3591.     cmp al, Esc        ; Hit an escape?
  3592.      je ED_pdone        ;  Hit the end, don't store Esc
  3593.     cmp cx, 100        ; Got too many chars?
  3594.      jae ED_pdone        ;  Don't take too many
  3595.  
  3596.     stosb            ; Store char in our buffer
  3597.     inc cx            ; Count the character
  3598.     mov Preload_flag, 0FFh    ; Flag that there is a preloaded command
  3599.     jmp ED_ploop        ; Do more
  3600.  
  3601. ED_p_no_more:
  3602.     pop di            ; Fix up stack
  3603.     jmp No_more_chars    ; Try again later
  3604.  
  3605. ED_pdone:
  3606.     sub al, al        ; Make a zero
  3607.     stosb            ; Tie off the string
  3608.  
  3609. ED_ignore:
  3610.     jmp Done_with_char
  3611.  
  3612. ED_0:    mov cx, Number_of_chars_on_VT100_screen  ; Start with this number
  3613.     mov al, Row        ; Which row we are on
  3614.     mov bh, Number_of_columns ; Words per row
  3615.     mul bh            ; Total number of words above us on screen
  3616.     mov bx, ax        ; Copy to bx
  3617.     mov al, Column        ; Current column
  3618.     cbw            ; Make full word
  3619.     add ax, bx        ; Total number of chars "above" us
  3620.     sub cx, ax        ; Numbers of words still to clear
  3621.     mov di, Char_ptr    ; Where to start clobbering
  3622.     cld            ; Move forward
  3623.     jmp ED_z        ; Go finish up ...    
  3624.  
  3625. ED_1:    mov al, Row        ; Which row we are on
  3626.     mov bh, Number_of_columns ; Words per row
  3627.     mul bh            ; Total number of words above us on screen
  3628.     mov cx, ax        ; Copy to cx
  3629.     mov al, Column        ; Current column
  3630.     cbw            ; Make full word
  3631.     inc ax            ; Bump by one to include current position
  3632.     add cx, ax        ; Total number of chars "above" us
  3633.     mov di, Char_ptr    ; Where to start clobbering
  3634.     std            ; Move backward
  3635.     jmp ED_z        ; Go finish up ...    
  3636.  
  3637. ED_2:    mov cx, Number_of_chars_on_VT100_screen  ; Number of chars to lay down
  3638.     mov di, OFFSET Screen_Image ; Where to put them
  3639.     cld            ; Move forward
  3640.  
  3641. ED_z:    mov ax, Alloc_ds    ; Allocated segment
  3642.     mov es, ax        ; Set up es
  3643.     ASSUME es:Alloc
  3644.  
  3645.     mov ax, 0720h        ; Want normal spaces
  3646.     rep stosw        ; Clear ...
  3647.  
  3648.     mov ax, Datas_ds    ; Normal segment
  3649.     mov es, ax        ; Set up es
  3650.     ASSUME es:Datas
  3651.  
  3652.     or Screen_flags, Screen_changed ; Flag screen change
  3653.     jmp ED_ignore
  3654.  
  3655.  
  3656. ; Erase in Line
  3657.  
  3658.     PUBLIC EL
  3659.  
  3660. EL:    call Default_zero    ; Get a param
  3661.  
  3662.     cmp al, 2        ; Is it too high?
  3663.      jg EL_ignore        ;  Yes ...
  3664.  
  3665.     cbw            ; Blow up to full word
  3666.     shl ax, 1        ; Double offset for words
  3667.     mov bx, ax        ; Copy to bx
  3668.     jmp EL_Table[bx]    ; Dispatch thru table to correct routine
  3669.  
  3670. EL_0:    mov cx, Number_of_columns ; Start with this number
  3671.     mov al, Column        ; Column number we are in
  3672.     cbw            ; Make full word
  3673.     sub cx, ax        ; Number of chars to our right
  3674.     mov di, Char_ptr    ; Where to start clobbering
  3675.     cld            ; Move forward
  3676.     jmp EL_z        ; Go finish up ...    
  3677.  
  3678. EL_1:    mov al, Column        ; Which column we are in
  3679.     cbw            ; Make full word
  3680.     inc ax            ; Bump by one to include current position
  3681.     mov cx, ax        ; Copy to cx
  3682.     mov di, Char_ptr    ; Where to start clobbering
  3683.     std            ; Move backward
  3684.     jmp EL_z        ; Go finish up ...    
  3685.  
  3686. EL_2:    mov cx, Number_of_columns ; Number of words to lay down
  3687.     mov di, Line_ptr    ; Where to put the bytes
  3688.     cld            ; Move forward
  3689.  
  3690. EL_z:    mov ax, Alloc_ds    ; Allocated segment
  3691.     mov es, ax        ; Set up es
  3692.     ASSUME es:Alloc
  3693.  
  3694.     mov ax, 0720h        ; Get a space, normal attribute
  3695.     rep stosw        ; Zap the buffer
  3696.  
  3697.     mov ax, Datas_ds    ; Normal segment
  3698.     mov es, ax        ; Set up es
  3699.     ASSUME es:Datas
  3700.  
  3701.     or Screen_flags, Screen_changed ; Flag screen change
  3702.  
  3703. EL_ignore:
  3704.     jmp Done_with_char
  3705.  
  3706.  
  3707. ; Horizontal and Vertical Position
  3708.  
  3709. HVP:    jmp CUP            ; Same thing as cursor position
  3710.  
  3711.  
  3712. ; Index
  3713.  
  3714. IND:    call Move_down_scroll_up ; Create a new line, the usual way ...
  3715.     jmp Done_with_char
  3716.  
  3717.  
  3718. ; Media Copy
  3719.  
  3720.     PUBLIC MC
  3721.  
  3722. MC:    call Default_zero    ; Get the first parameter, default is 0
  3723.  
  3724. MC_Loop: or al, al        ; See if negative
  3725.       js MC_Ignore        ; Negative, ignore it
  3726.  
  3727.     cmp al, 5        ; Highest value we have code for
  3728.      jg MC_Ignore        ; Can't handle it
  3729.  
  3730.     cbw            ; Blow up to full word
  3731.     shl ax, 1        ; Double offset for words
  3732.     mov bx, ax        ; Copy to bx
  3733.     jmp MC_Table[bx]    ; Dispatch thru table to correct routine
  3734.  
  3735. ; Print screen, not implemented
  3736.  
  3737. MC_0:    jmp SHORT MC_Ignore
  3738.  
  3739. ; Print cursor line, not implemented
  3740.  
  3741. MC_1:    jmp SHORT MC_Ignore
  3742.  
  3743. ; Printer controller off, or Auto print off
  3744.  
  3745. MC_4:    test VT100_status_flags, Private_esc_seq
  3746.      jz MC4_x        ;  Not private
  3747.  
  3748.     and VT100_status_flags, NOT Auto_copy_mode ; Turn it off
  3749.     jmp SHORT MC_Ignore
  3750.  
  3751. MC4_x:    and VT100_status_flags, NOT Printer_controller_mode ; Turn it off
  3752.     jmp SHORT MC_Ignore
  3753.  
  3754. ; Printer controller on, or Auto print on
  3755.  
  3756. MC_5:    test VT100_status_flags, Private_esc_seq
  3757.      jz MC5_x        ;  Not private
  3758.  
  3759.     or VT100_status_flags, Auto_copy_mode ; Turn it on
  3760.     jmp SHORT MC_Ignore
  3761.  
  3762. MC5_x:    or VT100_status_flags, Printer_controller_mode ; Turn it on
  3763.  
  3764. MC_Ignore: mov Prev_shift_state, 0FFh ; Force set up of new mode line
  3765.     jmp Done_with_char    ; Done with this one
  3766.  
  3767.  
  3768. ; Next Line
  3769.  
  3770. NEL:    mov Column, 0        ; Clear the column offset
  3771.     jmp IND            ; Join common code
  3772.  
  3773.  
  3774. ; Reverse Index
  3775.  
  3776. RI:    call Move_up_scroll_down ; Create a new line, the other way ...
  3777.     jmp Done_with_char
  3778.  
  3779.  
  3780. ; Reset Mode
  3781.  
  3782.     PUBLIC RM
  3783.  
  3784. RM:    call Default_zero    ; Get the first parameter, default is 0
  3785.  
  3786. RM_1:    cmp al, 1        ; One?
  3787.      jne RM_2        ;  No
  3788.  
  3789.     and VT100_status_flags, NOT Cursor_keys_mode ; Turn off the bit
  3790.  
  3791. RM_2:    call Get_next_number    ; Try to get another number
  3792.      jmp Done_with_char
  3793.  
  3794.     jmp RM_1        ; Got one, go do something with it
  3795.  
  3796.  
  3797. ; Select Graphic Rendition
  3798.  
  3799.     PUBLIC SGR
  3800.  
  3801. SGR:    call Default_zero    ; Get the first parameter, default zero
  3802.  
  3803. SGR_Loop:
  3804.     or al, al        ; See if negative
  3805.      js SGR_Ignore        ; Negative, ignore it
  3806.  
  3807.     cmp al, 7        ; Highest value we have code for
  3808.      jg SGR_Ignore        ; Can't handle it
  3809.  
  3810.     cbw            ; Blow up to full word
  3811.     shl ax, 1        ; Double offset for words
  3812.     mov bx, ax        ; Copy to bx
  3813.     jmp SGR_Table[bx]    ; Dispatch thru table to correct routine
  3814.  
  3815. SGR_0:    mov al, NOT (Blinking + Bold + Inverted + Underscored)
  3816.                 ; These renditions ...
  3817.     and Rendition, al    ; Turn off those bits ... 
  3818.     jmp SHORT SGR_Ignore    ; Done with this part
  3819.  
  3820. SGR_1:    mov al, Bold        ; Flag for bold
  3821.     jmp SHORT SGR_Set    ; Go set the bit
  3822.  
  3823. SGR_4:    mov al, Underscored    ; Flag for underscored
  3824.     jmp SHORT SGR_Set    ; Go set the bit
  3825.  
  3826. SGR_5:    mov al, Blinking    ; Flag for blinking
  3827.     jmp SHORT SGR_Set    ; Go set the bit
  3828.  
  3829. SGR_7:    mov al, Inverted    ; Flag for inverted
  3830.  
  3831. SGR_Set: or Rendition, al    ; Set the bit
  3832.  
  3833. SGR_Ignore:
  3834.     call Get_next_number    ; Try to get another number
  3835.      jmp SHORT SGR_Done    ;  No such luck ... 
  3836.      nop            ;  3 bytes
  3837.  
  3838.     jmp SGR_Loop        ; Got one, go do something with it
  3839.  
  3840. SGR_Done:
  3841.     call Set_attribute_byte    ; Set attr based on rendition
  3842.     jmp Done_with_char    ; Done with this one
  3843.  
  3844.  
  3845. ; Set Mode
  3846.  
  3847.     PUBLIC SM
  3848.  
  3849. SM:    call Default_zero    ; Get the first parameter, default is 0
  3850.  
  3851. SM_1:    cmp al, 1        ; One?
  3852.      jne SM_2        ;  No
  3853.  
  3854.     or VT100_status_flags, Cursor_keys_mode ; Turn on the bit
  3855.  
  3856. SM_2:    call Get_next_number    ; Try to get another number
  3857.      jmp Done_with_char
  3858.  
  3859.     jmp SM_1        ; Got one, go do something with it
  3860.  
  3861. VT100_Routines ENDP
  3862.  
  3863. Code    ENDS
  3864.  
  3865.     END
  3866. 
  3867.